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();