1/*! { "name": "vissense", "version": "0.9.0", "homepage": "https://vissense.github.io/vissense","copyright": "(c) 2016 tbk" } */ 2!function(root, name, factory) { 3 "use strict"; 4 var withWindow = function(win) { 5 var product = factory(win, win.document); 6 return product.noConflict = function() { 7 return product; 8 }, product; 9 }; 10 if ("function" == typeof define && define.amd) define([], function() { 11 return withWindow; 12 }); else if ("object" == typeof exports) module.exports = function(win) { 13 return withWindow(win); 14 }; else { 15 var _oldValue = root[name], _newValue = factory(root, root.document); 16 root[name] = _newValue, root[name].noConflict = function() { 17 return root[name] = _oldValue, _newValue; 18 }; 19 } 20}(this, "VisSense", function(window, document, undefined) { 21 "use strict"; 22 function async(callback, delay) { 23 return function() { 24 var args = arguments; 25 return defer(function() { 26 callback.apply(undefined, args); 27 }, delay || 0); 28 }; 29 } 30 function debounce(callback, delay) { 31 var cancel = noop; 32 return function() { 33 var self = this, args = arguments; 34 cancel(), cancel = defer(function() { 35 callback.apply(self, args); 36 }, delay); 37 }; 38 } 39 function defaults(dest, source) { 40 var sourceIsObject = isObject(source), destIsObject = isObject(dest); 41 return sourceIsObject || destIsObject ? sourceIsObject && destIsObject ? (forEach(Object.keys(source), function(property) { 42 dest[property] === undefined && (dest[property] = source[property]); 43 }), dest) : sourceIsObject ? source : dest : source; 44 } 45 function defer(callback, delay) { 46 var timer = setTimeout(function() { 47 callback(); 48 }, delay || 0); 49 return function() { 50 clearTimeout(timer); 51 }; 52 } 53 function fireIf(when, callback) { 54 return function() { 55 return (isFunction(when) ? when() : when) ? callback() : undefined; 56 }; 57 } 58 function extend(dest, source, callback) { 59 for (var index = -1, props = Object.keys(source), length = props.length, ask = isFunction(callback); ++index < length; ) { 60 var key = props[index]; 61 dest[key] = ask ? callback(dest[key], source[key], key, dest, source) : source[key]; 62 } 63 return dest; 64 } 65 function forEach(array, callback, thisArg) { 66 for (var i = 0, n = array.length; n > i; i++) { 67 var result = callback.call(thisArg, array[i], i, array); 68 if (result !== undefined) return result; 69 } 70 } 71 function identity(value) { 72 return value; 73 } 74 function isDefined(value) { 75 return value !== undefined; 76 } 77 function isArray(value) { 78 return value && "object" == typeof value && "number" == typeof value.length && "[object Array]" === Object.prototype.toString.call(value) || !1; 79 } 80 function isElement(value) { 81 return value && 1 === value.nodeType || !1; 82 } 83 function isFunction(value) { 84 return "function" == typeof value || !1; 85 } 86 function isObject(value) { 87 var type = typeof value; 88 return "function" === type || value && "object" === type || !1; 89 } 90 function noop() {} 91 function now() { 92 return new Date().getTime(); 93 } 94 function once(callback) { 95 var cache, called = !1; 96 return function() { 97 return called || (cache = callback.apply(undefined, arguments), called = !0), cache; 98 }; 99 } 100 function throttle(callback, wait, thisArg) { 101 var cancel = noop, last = !1; 102 return function() { 103 var time = now(), args = arguments, func = function() { 104 last = time, callback.apply(thisArg, args); 105 }; 106 last && last + wait > time ? (cancel(), cancel = defer(func, wait)) : (last = time, 107 defer(func, 0)); 108 }; 109 } 110 function viewport(referenceWindow) { 111 var win = referenceWindow || window; 112 return { 113 height: win.innerHeight, 114 width: win.innerWidth 115 }; 116 } 117 function computedStyle(element, referenceWindow) { 118 return (referenceWindow || window).getComputedStyle(element, null); 119 } 120 function styleProperty(style, property) { 121 return style.getPropertyValue(property); 122 } 123 function isDisplayed(element, style) { 124 style || (style = computedStyle(element)); 125 var display = styleProperty(style, "display"); 126 if ("none" === display) return !1; 127 var parent = element.parentNode; 128 return isElement(parent) ? isDisplayed(parent) : !0; 129 } 130 function isVisibleByStyling(element, referenceWindow) { 131 if (element === (referenceWindow || window).document) return !0; 132 if (!element || !element.parentNode) return !1; 133 var style = computedStyle(element, referenceWindow), visibility = styleProperty(style, "visibility"); 134 return "hidden" === visibility || "collapse" === visibility ? !1 : isDisplayed(element, style); 135 } 136 function isInViewport(rect, viewport) { 137 return !rect || rect.width <= 0 || rect.height <= 0 ? !1 : rect.bottom > 0 && rect.right > 0 && rect.top < viewport.height && rect.left < viewport.width; 138 } 139 function percentage(element, referenceWindow) { 140 var rect = element.getBoundingClientRect(), view = viewport(referenceWindow); 141 if (!isInViewport(rect, view) || !isVisibleByStyling(element)) return 0; 142 var vh = 0, vw = 0; 143 return rect.top >= 0 ? vh = Math.min(rect.height, view.height - rect.top) : rect.bottom > 0 && (vh = Math.min(view.height, rect.bottom)), 144 rect.left >= 0 ? vw = Math.min(rect.width, view.width - rect.left) : rect.right > 0 && (vw = Math.min(view.width, rect.right)), 145 vh * vw / (rect.height * rect.width); 146 } 147 function isPageVisible(referenceWindow) { 148 return !createVisibilityApi(referenceWindow || window).isHidden(); 149 } 150 function VisSense(element, config) { 151 if (!(this instanceof VisSense)) return new VisSense(element, config); 152 if (!isElement(element)) throw new Error("not an element node"); 153 this._element = element, this._config = defaults(config, { 154 fullyvisible: 1, 155 hidden: 0, 156 referenceWindow: window, 157 percentageHook: percentage, 158 precision: 3, 159 visibilityHooks: [] 160 }); 161 var roundFactor = this._config.precision <= 0 ? 1 : Math.pow(10, this._config.precision || 3); 162 this._round = function(val) { 163 return Math.round(val * roundFactor) / roundFactor; 164 }; 165 var visibilityApi = createVisibilityApi(this._config.referenceWindow); 166 this._config.visibilityHooks.push(function() { 167 return !visibilityApi.isHidden(); 168 }); 169 } 170 function nextState(visobj, currentState) { 171 var newState = visobj.state(), percentage = newState.percentage; 172 return currentState && percentage === currentState.percentage && currentState.percentage === currentState.previous.percentage ? currentState : newState.hidden ? VisSense.VisState.hidden(percentage, currentState) : newState.fullyvisible ? VisSense.VisState.fullyvisible(percentage, currentState) : VisSense.VisState.visible(percentage, currentState); 173 } 174 function VisMon(visobj, config) { 175 var _config = defaults(config, { 176 strategy: [ new VisMon.Strategy.PollingStrategy(), new VisMon.Strategy.EventStrategy() ], 177 async: !1 178 }); 179 this._visobj = visobj, this._state = {}, this._started = !1;
180 var anyTopicName = "*#" + now(); 181 this._pubsub = new PubSub({ 182 async: _config.async, 183 anyTopicName: anyTopicName 184 }), this._events = [ anyTopicName, "start", "stop", "update", "hidden", "visible", "fullyvisible", "percentagechange", "visibilitychange" ], 185 this._strategy = new VisMon.Strategy.CompositeStrategy(_config.strategy), this._strategy.init(this), 186 this._pubsub.on("update", function(monitor) { 187 var newValue = monitor._state.percentage, oldValue = monitor._state.previous.percentage; 188 newValue !== oldValue && monitor._pubsub.publish("percentagechange", [ monitor, newValue, oldValue ]); 189 }), this._pubsub.on("update", function(monitor) { 190 monitor._state.code !== monitor._state.previous.code && monitor._pubsub.publish("visibilitychange", [ monitor ]); 191 }), this._pubsub.on("visibilitychange", function(monitor) { 192 monitor._state.visible && !monitor._state.previous.visible && monitor._pubsub.publish("visible", [ monitor ]); 193 }), this._pubsub.on("visibilitychange", function(monitor) { 194 monitor._state.fullyvisible && monitor._pubsub.publish("fullyvisible", [ monitor ]); 195 }), this._pubsub.on("visibilitychange", function(monitor) { 196 monitor._state.hidden && monitor._pubsub.publish("hidden", [ monitor ]); 197 }), forEach(this._events, function(event) { 198 isFunction(_config[event]) && this.on(event, _config[event]); 199 }, this); 200 } 201 var createVisibilityApi = function(referenceWindow) { 202 return function(document, undefined) { 203 var entry = function(propertyName, eventName) { 204 return { 205 property: propertyName, 206 event: eventName 207 }; 208 }, event = "visibilitychange", dict = [ entry("webkitHidden", "webkit" + event), entry("msHidden", "ms" + event), entry("mozHidden", "moz" + event), entry("hidden", event) ], api = forEach(dict, function(entry) { 209 return document[entry.property] !== undefined ? { 210 isHidden: function() { 211 return !!document[entry.property] || !1; 212 }, 213 onVisibilityChange: function(callback) { 214 return document.addEventListener(entry.event, callback, !1), function() { 215 document.removeEventListener(entry.event, callback, !1); 216 }; 217 } 218 } : void 0; 219 }); 220 return api || { 221 isHidden: function() { 222 return !1; 223 }, 224 onVisibilityChange: function() { 225 return noop; 226 } 227 }; 228 }((referenceWindow || window).document); 229 }, PubSub = function(undefined) { 230 function PubSub(config) { 231 this._cache = {}, this._onAnyCache = [], this._config = defaults(config, { 232 async: !1, 233 anyTopicName: "*" 234 }); 235 } 236 var syncFireListeners = function(consumers, args) { 237 forEach(consumers, function(consumer) { 238 consumer(args); 239 }); 240 }; 241 return PubSub.prototype.on = function(topic, callback) { 242 if (!isFunction(callback)) return noop; 243 var applyCallback = function(args) { 244 return callback.apply(undefined, args || []); 245 }, listener = this._config.async ? async(applyCallback) : applyCallback, unregister = function(listener, array, topic) { 246 return function() { 247 var index = array.indexOf(listener); 248 return index > -1 ? (array.splice(index, 1), !0) : !1; 249 }; 250 }; 251 return topic === this._config.anyTopicName ? (this._onAnyCache.push(listener), unregister(listener, this._onAnyCache, "*")) : (this._cache[topic] || (this._cache[topic] = []), 252 this._cache[topic].push(listener), unregister(listener, this._cache[topic], topic)); 253 }, PubSub.prototype.publish = function(topic, args) { 254 var listeners = (this._cache[topic] || []).concat(topic === this._config.anyTopicName ? [] : this._onAnyCache), enableAsync = !!this._config.async, syncOrAsyncPublish = enableAsync ? async(syncFireListeners) : function(listeners, args) { 255 return syncFireListeners(listeners, args), noop; 256 }; 257 return syncOrAsyncPublish(listeners, args || []); 258 }, PubSub; 259 }(); 260 VisSense.prototype.state = function() { 261 var hiddenByHook = forEach(this._config.visibilityHooks, function(hook) { 262 return hook(this._element) ? void 0 : VisSense.VisState.hidden(0); 263 }, this); 264 return hiddenByHook || function(visobj, element, config) { 265 var perc = visobj._round(config.percentageHook(element, config.referenceWindow)); 266 return perc <= config.hidden ? VisSense.VisState.hidden(perc) : perc >= config.fullyvisible ? VisSense.VisState.fullyvisible(perc) : VisSense.VisState.visible(perc); 267 }(this, this._element, this._config); 268 }, VisSense.prototype.percentage = function() { 269 return this.state().percentage; 270 }, VisSense.prototype.element = function() { 271 return this._element; 272 }, VisSense.prototype.referenceWindow = function() { 273 return this._config.referenceWindow; 274 }, VisSense.prototype.isFullyVisible = function() { 275 return this.state().fullyvisible; 276 }, VisSense.prototype.isVisible = function() { 277 return this.state().visible; 278 }, VisSense.prototype.isHidden = function() { 279 return this.state().hidden; 280 }, VisSense.fn = VisSense.prototype, VisSense.of = function(element, config) { 281 return new VisSense(element, config); 282 }; 283 var STATES = { 284 HIDDEN: [ 0, "hidden" ], 285 VISIBLE: [ 1, "visible" ], 286 FULLY_VISIBLE: [ 2, "fullyvisible" ] 287 }; 288 return VisSense.VisState = function() { 289 function newVisState(state, percentage, previous) { 290 return previous && delete previous.previous, { 291 code: state[0], 292 state: state[1], 293 percentage: percentage, 294 previous: previous || {}, 295 fullyvisible: state[0] === STATES.FULLY_VISIBLE[0], 296 visible: state[0] === STATES.VISIBLE[0] || state[0] === STATES.FULLY_VISIBLE[0], 297 hidden: state[0] === STATES.HIDDEN[0] 298 }; 299 } 300 return { 301 hidden: function(percentage, previous) { 302 return newVisState(STATES.HIDDEN, percentage, previous); 303 }, 304 visible: function(percentage, previous) { 305 return newVisState(STATES.VISIBLE, percentage, previous); 306 }, 307 fullyvisible: function(percentage, previous) { 308 return newVisState(STATES.FULLY_VISIBLE, percentage, previous); 309 } 310 }; 311 }(), VisMon.prototype.visobj = function() { 312 return this._visobj; 313 }, VisMon.prototype.publish = function(eventName, args) { 314 var isInternalEvent = this._events.indexOf(eventName) >= 0; 315 if (isInternalEvent) throw new Error('Cannot publish internal event "' + eventName + '" from external scope.'); 316 return this._pubsub.publish(eventName, args); 317 }, VisMon.prototype.state = function() { 318 return this._state; 319 }, VisMon.prototype.start = function(config) { 320 if (this._started) return this; 321 var _config = defaults(config, { 322 async: !1 323 }); 324 return this._cancelAsyncStart && this._cancelAsyncStart(), _config.async ? this.startAsync() : (this.update(), 325 this._pubsub.publish("start", [ this ]), this._strategy.start(this), this._started = !0, 326 this); 327 }, VisMon.prototype.startAsync = function(config) { 328 this._cancelAsyncStart && this._cancelAsyncStart(); 329 var me = this, cancelAsyncStart = defer(function() { 330 me.start(extend(defaults(config, {}), { 331 async: !1 332 })); 333 }); 334 return this._cancelAsyncStart = function() { 335 cancelAsyncStart(), me._cancelAsyncStart = null; 336 }, this; 337 }, VisMon.prototype.stop = function() { 338 this._cancelAsyncStart && this._cancelAsyncStart(), this._started && (this._strategy.stop(this), 339 this._pubsub.publish("stop", [ this ])), this._started = !1; 340 }, VisMon.prototype.update = function() { 341 this._state = nextState(this._visobj, this._state), this._pubsub.publish("update", [ this ]); 342 }, VisMon.prototype.on = function(topic, callback) { 343 return this._pubsub.on(topic, callback); 344 }, VisMon.Builder = function() { 345 var combineStrategies = function(config, strategies) { 346 var combinedStrategies = null, forceDisableStrategies = config.strategy === !1, enableStrategies = !forceDisableStrategies && (config.strategy || strategies.length > 0); 347 if (enableStrategies) { 348 var configStrategyIsDefined = !!config.strategy, configStrategyIsArray = isArray(config.strategy), configStrategyAsArray = configStrategyIsDefined ? configStrategyIsArray ? config.strategy : [ config.strategy ] : []; 349 combinedStrategies = configStrategyAsArray.concat(strategies); 350 } else combinedStrategies = forceDisableStrategies ? [] : config.strategy; 351 return combinedStrategies; 352 }; 353 return function(visobj) { 354 var config = {}, strategies = [], events = [], productBuilt = !1, product = null; 355 return { 356 set: function(name, value) { 357 return config[name] = value, this; 358 }, 359 strategy: function(strategy) { 360 return strategies.push(strategy), this; 361 }, 362 on: function(event, handler) { 363 return events.push([ event, handler ]), this; 364 }, 365 build: function(consumer) { 366 var manufacture = function() { 367 var combinedStrategies = combineStrategies(config, strategies); 368 config.strategy = combinedStrategies; 369 var monitor = visobj.monitor(config); 370 return forEach(events, function(event) { 371 monitor.on(event[0], event[1]); 372 }), productBuilt = !0, product = monitor; 373 }, monitor = productBuilt ? product : manufacture(); 374 return isFunction(consumer) ? consumer(monitor) : monitor; 375 } 376 }; 377 }; 378 }(), VisMon.Strategy = function() {}, VisMon.Strategy.prototype.init = noop, VisMon.Strategy.prototype.start = noop, 379 VisMon.Strategy.prototype.stop = noop, VisMon.Strategy.CompositeStrategy = function(strategies) { 380 this._strategies = isArray(strategies) ? strategies : [ strategies ]; 381 }, VisMon.Strategy.CompositeStrategy.prototype = Object.create(VisMon.Strategy.prototype), 382 VisMon.Strategy.CompositeStrategy.prototype.init = function(monitor) {
383 forEach(this._strategies, function(strategy) { 384 isFunction(strategy.init) && strategy.init(monitor); 385 }); 386 }, VisMon.Strategy.CompositeStrategy.prototype.start = function(monitor) { 387 forEach(this._strategies, function(strategy) { 388 isFunction(strategy.start) && strategy.start(monitor); 389 }); 390 }, VisMon.Strategy.CompositeStrategy.prototype.stop = function(monitor) { 391 forEach(this._strategies, function(strategy) { 392 isFunction(strategy.stop) && strategy.stop(monitor); 393 }); 394 }, VisMon.Strategy.PollingStrategy = function(config) { 395 this._config = defaults(config, { 396 interval: 1e3 397 }), this._started = !1; 398 }, VisMon.Strategy.PollingStrategy.prototype = Object.create(VisMon.Strategy.prototype), 399 VisMon.Strategy.PollingStrategy.prototype.start = function(monitor) { 400 return this._started || (this._clearInterval = function(interval) { 401 var intervalId = setInterval(function() { 402 monitor.update(); 403 }, interval); 404 return function() { 405 clearInterval(intervalId); 406 }; 407 }(this._config.interval), this._started = !0), this._started; 408 }, VisMon.Strategy.PollingStrategy.prototype.stop = function() { 409 return this._started ? (this._clearInterval(), this._started = !1, !0) : !1; 410 }, VisMon.Strategy.EventStrategy = function(config) { 411 this._config = defaults(config, { 412 throttle: 50 413 }), this._config.debounce > 0 && (this._config.throttle = +this._config.debounce), 414 this._started = !1; 415 }, VisMon.Strategy.EventStrategy.prototype = Object.create(VisMon.Strategy.prototype), 416 VisMon.Strategy.EventStrategy.prototype.start = function(monitor) { 417 return this._started || (this._removeEventListeners = function(update) { 418 var referenceWindow = monitor.visobj().referenceWindow(), visibilityApi = createVisibilityApi(referenceWindow), removeOnVisibilityChangeEvent = visibilityApi.onVisibilityChange(update); 419 return referenceWindow.addEventListener("scroll", update, !1), referenceWindow.addEventListener("resize", update, !1), 420 referenceWindow.addEventListener("touchmove", update, !1), function() { 421 referenceWindow.removeEventListener("touchmove", update, !1), referenceWindow.removeEventListener("resize", update, !1), 422 referenceWindow.removeEventListener("scroll", update, !1), removeOnVisibilityChangeEvent(); 423 }; 424 }(throttle(function() { 425 monitor.update(); 426 }, this._config.throttle)), this._started = !0), this._started; 427 }, VisMon.Strategy.EventStrategy.prototype.stop = function() { 428 return this._started ? (this._removeEventListeners(), this._started = !1, !0) : !1; 429 }, VisSense.VisMon = VisMon, VisSense.PubSub = PubSub, VisSense.fn.monitor = function(config) { 430 return new VisMon(this, config); 431 }, VisSense.Utils = { 432 async: async, 433 debounce: debounce, 434 defaults: defaults, 435 defer: defer, 436 extend: extend, 437 forEach: forEach, 438 fireIf: fireIf, 439 identity: identity, 440 isArray: isArray, 441 isDefined: isDefined, 442 isElement: isElement, 443 isFunction: isFunction, 444 isObject: isObject, 445 isPageVisible: isPageVisible, 446 isVisibleByStyling: isVisibleByStyling, 447 noop: noop, 448 now: now, 449 once: once, 450 throttle: throttle, 451 percentage: percentage, 452 VisibilityApi: createVisibilityApi(), 453 createVisibilityApi: createVisibilityApi, 454 _viewport: viewport, 455 _isInViewport: isInViewport, 456 _isDisplayed: isDisplayed, 457 _computedStyle: computedStyle, 458 _styleProperty: styleProperty 459 }, VisSense; 460});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.