UNPKG

qoopido.nucleus

Version:

Lightweight, atomic and modular JavaScript utility library that strongly encourages the creation and usage of small yet flexible, reusable and easily maintainable modules.

148 lines (114 loc) 3.72 kB
/** * @use /demand/weakmap * * @require ../element * @require ../../function/merge * @require ../../function/debounce */ (function(global, document, setInterval) { 'use strict'; if(document.compatMode !== 'CSS1Compat') { throw new Error('Browser needs to be in standards mode'); } function definition(Weakmap, DomElement, functionMerge, functionDebounce) { var documentElement = document.documentElement, window = new DomElement(global), viewport = {}, storage = new Weakmap(), elements = [], EVENTS_RESIZE = 'resize orientationchange', EVENT_APPEAR = 'appear', EVENT_DISAPPEAR = 'disappear'; window.on(EVENTS_RESIZE, functionDebounce(updateViewport)); updateViewport(); setInterval(function() { var i = 0, element, properties, settings, state; for(; element = elements[i]; i++) { properties = storage.get(element); settings = properties.settings; if(!settings.visibility || element.isVisible()) { state = check.call(element); if(state !== properties.state) { switch(state) { case 0: element.emit(EVENT_DISAPPEAR, { priority: 1 }); break; case 1: element.emit(properties.state <= 0 ? EVENT_APPEAR : EVENT_DISAPPEAR, { priority: 2 }); break; case 2: element.emit(EVENT_APPEAR, { priority: 1 }); break; } properties.state = state; } if(!settings.recur && state === 2) { elements.splice(i, 1); i--; } } } }, 1000 / 30); function updateViewport() { viewport.left = 0; viewport.top = 0; viewport.right = global.innerWidth || documentElement.clientWidth; viewport.bottom = global.innerHeight || documentElement.clientHeight; } function updateBoundaries() { var properties = storage.get(this), settings = properties.settings, boundaries = properties.boundaries, treshold = settings.threshold, x = (treshold !== undefined) ? treshold : documentElement.clientWidth * settings.auto, y = (treshold !== undefined) ? treshold : documentElement.clientHeight * settings.auto; boundaries.left = viewport.left - x; boundaries.top = viewport.top - y; boundaries.right = viewport.right + x; boundaries.bottom = viewport.bottom + y; } function isWithinBoundaries(element, boundaries) { var rect = element.getBoundingClientRect(); if(rect.right <= boundaries.left || rect.bottom <= boundaries.top || rect.left >= boundaries.right || rect.top >= boundaries.bottom) { return false; } return true; } function check() { var self = this, node = self.node, properties = storage.get(self); if(isWithinBoundaries(node, viewport)) { return 2; } if(isWithinBoundaries(node, properties.boundaries)) { return 1; } return 0; } function DomElementAppear(element, settings) { var self = DomElement.call(this, element); settings = functionMerge({}, DomElementAppear.settings, settings); if(settings.threshold === 'auto') { delete settings.threshold; } storage.set(self, { settings: settings, boundaries: {}, state: -1 }); window.on(EVENTS_RESIZE, functionDebounce(updateBoundaries.bind(self))); updateBoundaries.call(self); elements.push(self); return self; } DomElementAppear.settings = { threshold: 'auto', recur: true, auto: 1, visibility: true }; return DomElementAppear.extends(DomElement); } provide([ '/demand/weakmap', '../element', '../../function/merge', '../../function/debounce' ], definition); }(this, document, setInterval));