lib/watir/dom/extensions/js/waitForDom.js in watir-dom-wait-0.2.0 vs lib/watir/dom/extensions/js/waitForDom.js in watir-dom-wait-0.2.1
- old
+ new
@@ -1,145 +1,92 @@
-/**
- * There is a number of required functions provided by Underscore.js,
- * but since we don't want to depend on it, we just copy-paste required
- * things.
- *
- * See http://underscorejs.org/docs/underscore.html for explanation of functions.
- */
+// arguments from WebDriver
+var element = arguments[0];
+var interval = arguments[1] * 1000;
+var delay = arguments[2] * 1000;
+var timeout = arguments[3] * 1000;
+var exit = arguments[4];
-var Underscore = {
- slice: Array.prototype.slice,
+// flag that DOM has started modifying
+var startedModifying = false;
- nativeBind: Function.prototype.bind,
+// exits codes
+var exits = {
+ modified: 0, // DOM modifications have started and successfully finished
+ timeout: 1, // DOM modifications have started but exceeded timeout
+ noop: 2, // DOM modifications have not started
+}
- once: function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
- };
- },
-
- delay: function(func, wait) {
- var args = this.slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- },
-
- debounce: function(func, wait, immediate) {
- var timeout, result;
- return function() {
- var context = this, args = arguments;
- var later = function() {
+/**
+ * Copy-paste of Underscore.js debounce function.
+ * @see http://underscorejs.org/docs/underscore.html#section-67
+ */
+var _debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = new Date();
+ var later = function() {
+ var last = (new Date()) - timestamp;
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
+ } else {
timeout = null;
if (!immediate) result = func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) result = func.apply(context, args);
- return result;
+ }
};
- },
-
- bind: function(func, context) {
- if (func.bind === this.nativeBind && this.nativeBind) return this.nativeBind.apply(func, this.slice.call(arguments, 1));
- var args = this.slice.call(arguments, 2);
- return function() {
- return func.apply(context, args.concat(this.slice.call(arguments)));
- };
- }
-};
-
-function Watir(options) {
- this.set(options);
-
- this.startedModifying = false;
- this.domReady = 1;
- this.observers = {
- forceReady: null,
- startModifying: null
- }
-
- this.addObservers();
- this.exitOnTimeout();
-};
-
-Watir.prototype.set = function(options) {
- if (options == null) {
- options = {};
- }
-
- this.el = options.el;
- this.interval = options.interval;
- this.delay = options.delay;
-
- this.forceReady = this.wrappedForceReady();
- this.startModifying = this.wrappedStartModifying();
-}
-
-Watir.prototype.exitOnTimeout = function() {
- var that = this;
-
- Underscore.delay(function() {
- if (!that.startedModifying) {
- that._forceReady();
+ var callNow = immediate && !timeout;
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
}
- }, this.delay);
-};
-
-Watir.prototype.addObservers = function() {
- this.observers.forceReady = this.observe(this.el, this.forceReady);
- this.observers.startModifying = this.observe(this.el, this.startModifying);
-}
-
-Watir.prototype.removeObservers = function() {
- this.unobserve(this.observers.forceReady);
- this.unobserve(this.observers.startModifying);
-}
-
-Watir.prototype.observe = function(el, fn) {
- var observer = new MutationObserver(function(mutations) {
- fn();
- });
- var config = {
- attributes: true,
- childList: true,
- characterData: true,
- subtree: true
+ if (callNow) result = func.apply(context, args);
+ return result;
};
- observer.observe(el, config);
- return observer;
};
-Watir.prototype.unobserve = function(observer) {
+/**
+ * Disconnects observer and
+ * invokes WebDriver's callback function
+ * to show that DOM has finished modifying.
+ */
+var exitOnModified = _debounce(function() {
+ clearTimeout(exitTimeout);
observer.disconnect();
-};
+ exit(exits.modified);
+}, interval);
-Watir.prototype.wrappedForceReady = function() {
- return Underscore.bind(Underscore.debounce(this._forceReady, this.interval), this);
-};
-
-Watir.prototype.wrappedStartModifying = function() {
- return Underscore.bind(Underscore.once(this._startModifying, this.interval), this);
+/**
+ * Disconnects observer and
+ * invokes WebDriver's callback function
+ * to show that DOM has started modifying
+ * but exceeded timeout.
+ */
+var exitOnTimeout = function() {
+ return setTimeout(function() {
+ observer.disconnect();
+ exit(exits.timeout);
+ }, timeout);
}
-Watir.prototype._forceReady = function(mutations) {
- var that = this;
-
- Underscore.once(function() {
- that.removeObservers();
- that.domReady -= 1;
- })();
+/**
+ * Disconnects observer and
+ * invokes WebDriver's callback function
+ * to show that DOM has not started modifying.
+ */
+var exitNoop = function() {
+ setTimeout(function() {
+ if (!startedModifying) {
+ clearTimeout(exitTimeout);
+ observer.disconnect();
+ exit(exits.noop);
+ }
+ }, delay);
}
-Watir.prototype._startModifying = function() {
- this.startedModifying = true;
-}
-
-window.watir = new Watir({
- el: arguments[0],
- interval: arguments[1] * 1000,
- delay: arguments[2] * 1000,
+var observer = new MutationObserver(function() {
+ if (!startedModifying) startedModifying = true;
+ exitOnModified();
});
+var config = { attributes: true, childList: true, characterData: true, subtree: true };
+observer.observe(element, config);
+var exitTimeout = exitOnTimeout();
+exitNoop();