Jelajahi Sumber

add arrive framework js

CauseFX 5 tahun lalu
induk
melakukan
dc4b37fabb
3 mengubah file dengan 471 tambahan dan 0 penghapusan
  1. 1 0
      index.php
  2. 461 0
      js/arrive.js
  3. 9 0
      js/arrive.min.js

+ 1 - 0
index.php

@@ -230,6 +230,7 @@ $Organizr = new Organizr();
 <script src="js/ua-parser.min.js"></script>
 <script src="js/plyr.js"></script>
 <script src="js/simplebar.js"></script>
+<script src="js/arrive.min.js"></script>
 <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
 <script src="js/functions.js?v=<?php echo $Organizr->fileHash; ?>"></script>
 <script src="js/custom.min.js?v=<?php echo $Organizr->fileHash; ?>"></script>

+ 461 - 0
js/arrive.js

@@ -0,0 +1,461 @@
+/*globals jQuery,Window,HTMLElement,HTMLDocument,HTMLCollection,NodeList,MutationObserver */
+/*exported Arrive*/
+/*jshint latedef:false */
+
+/*
+ * arrive.js
+ * v2.4.1
+ * https://github.com/uzairfarooq/arrive
+ * MIT licensed
+ *
+ * Copyright (c) 2014-2017 Uzair Farooq
+ */
+var Arrive = (function(window, $, undefined) {
+
+  "use strict";
+
+  if(!window.MutationObserver || typeof HTMLElement === 'undefined'){
+    return; //for unsupported browsers
+  }
+
+  var arriveUniqueId = 0;
+
+  var utils = (function() {
+    var matches = HTMLElement.prototype.matches || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector
+                  || HTMLElement.prototype.msMatchesSelector;
+
+    return {
+      matchesSelector: function(elem, selector) {
+        return elem instanceof HTMLElement && matches.call(elem, selector);
+      },
+      // to enable function overloading - By John Resig (MIT Licensed)
+      addMethod: function (object, name, fn) {
+        var old = object[ name ];
+        object[ name ] = function(){
+          if ( fn.length == arguments.length ) {
+            return fn.apply( this, arguments );
+          }
+          else if ( typeof old == 'function' ) {
+            return old.apply( this, arguments );
+          }
+        };
+      },
+      callCallbacks: function(callbacksToBeCalled, registrationData) {
+        if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) {
+          // as onlyOnce param is true, make sure we fire the event for only one item
+          callbacksToBeCalled = [callbacksToBeCalled[0]];
+        }
+
+        for (var i = 0, cb; (cb = callbacksToBeCalled[i]); i++) {
+          if (cb && cb.callback) {
+            cb.callback.call(cb.elem, cb.elem);
+          }
+        }
+
+        if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) {
+          // unbind event after first callback as onceOnly is true.
+          registrationData.me.unbindEventWithSelectorAndCallback.call(
+            registrationData.target, registrationData.selector, registrationData.callback);
+        }
+      },
+      // traverse through all descendants of a node to check if event should be fired for any descendant
+      checkChildNodesRecursively: function(nodes, registrationData, matchFunc, callbacksToBeCalled) {
+        // check each new node if it matches the selector
+        for (var i=0, node; (node = nodes[i]); i++) {
+          if (matchFunc(node, registrationData, callbacksToBeCalled)) {
+            callbacksToBeCalled.push({ callback: registrationData.callback, elem: node });
+          }
+
+          if (node.childNodes.length > 0) {
+            utils.checkChildNodesRecursively(node.childNodes, registrationData, matchFunc, callbacksToBeCalled);
+          }
+        }
+      },
+      mergeArrays: function(firstArr, secondArr){
+        // Overwrites default options with user-defined options.
+        var options = {},
+            attrName;
+        for (attrName in firstArr) {
+          if (firstArr.hasOwnProperty(attrName)) {
+            options[attrName] = firstArr[attrName];
+          }
+        }
+        for (attrName in secondArr) {
+          if (secondArr.hasOwnProperty(attrName)) {
+            options[attrName] = secondArr[attrName];
+          }
+        }
+        return options;
+      },
+      toElementsArray: function (elements) {
+        // check if object is an array (or array like object)
+        // Note: window object has .length property but it's not array of elements so don't consider it an array
+        if (typeof elements !== "undefined" && (typeof elements.length !== "number" || elements === window)) {
+          elements = [elements];
+        }
+        return elements;
+      }
+    };
+  })();
+
+
+  // Class to maintain state of all registered events of a single type
+  var EventsBucket = (function() {
+    var EventsBucket = function() {
+      // holds all the events
+
+      this._eventsBucket    = [];
+      // function to be called while adding an event, the function should do the event initialization/registration
+      this._beforeAdding    = null;
+      // function to be called while removing an event, the function should do the event destruction
+      this._beforeRemoving  = null;
+    };
+
+    EventsBucket.prototype.addEvent = function(target, selector, options, callback) {
+      var newEvent = {
+        target:             target,
+        selector:           selector,
+        options:            options,
+        callback:           callback,
+        firedElems:         []
+      };
+
+      if (this._beforeAdding) {
+        this._beforeAdding(newEvent);
+      }
+
+      this._eventsBucket.push(newEvent);
+      return newEvent;
+    };
+
+    EventsBucket.prototype.removeEvent = function(compareFunction) {
+      for (var i=this._eventsBucket.length - 1, registeredEvent; (registeredEvent = this._eventsBucket[i]); i--) {
+        if (compareFunction(registeredEvent)) {
+          if (this._beforeRemoving) {
+              this._beforeRemoving(registeredEvent);
+          }
+
+          // mark callback as null so that even if an event mutation was already triggered it does not call callback
+          var removedEvents = this._eventsBucket.splice(i, 1);
+          if (removedEvents && removedEvents.length) {
+            removedEvents[0].callback = null;
+          }
+        }
+      }
+    };
+
+    EventsBucket.prototype.beforeAdding = function(beforeAdding) {
+      this._beforeAdding = beforeAdding;
+    };
+
+    EventsBucket.prototype.beforeRemoving = function(beforeRemoving) {
+      this._beforeRemoving = beforeRemoving;
+    };
+
+    return EventsBucket;
+  })();
+
+
+  /**
+   * @constructor
+   * General class for binding/unbinding arrive and leave events
+   */
+  var MutationEvents = function(getObserverConfig, onMutation) {
+    var eventsBucket    = new EventsBucket(),
+        me              = this;
+
+    var defaultOptions = {
+      fireOnAttributesModification: false
+    };
+
+    // actual event registration before adding it to bucket
+    eventsBucket.beforeAdding(function(registrationData) {
+      var
+        target    = registrationData.target,
+        observer;
+
+      // mutation observer does not work on window or document
+      if (target === window.document || target === window) {
+        target = document.getElementsByTagName("html")[0];
+      }
+
+      // Create an observer instance
+      observer = new MutationObserver(function(e) {
+        onMutation.call(this, e, registrationData);
+      });
+
+      var config = getObserverConfig(registrationData.options);
+
+      observer.observe(target, config);
+
+      registrationData.observer = observer;
+      registrationData.me = me;
+    });
+
+    // cleanup/unregister before removing an event
+    eventsBucket.beforeRemoving(function (eventData) {
+      eventData.observer.disconnect();
+    });
+
+    this.bindEvent = function(selector, options, callback) {
+      options = utils.mergeArrays(defaultOptions, options);
+
+      var elements = utils.toElementsArray(this);
+
+      for (var i = 0; i < elements.length; i++) {
+        eventsBucket.addEvent(elements[i], selector, options, callback);
+      }
+    };
+
+    this.unbindEvent = function() {
+      var elements = utils.toElementsArray(this);
+      eventsBucket.removeEvent(function(eventObj) {
+        for (var i = 0; i < elements.length; i++) {
+          if (this === undefined || eventObj.target === elements[i]) {
+            return true;
+          }
+        }
+        return false;
+      });
+    };
+
+    this.unbindEventWithSelectorOrCallback = function(selector) {
+      var elements = utils.toElementsArray(this),
+          callback = selector,
+          compareFunction;
+
+      if (typeof selector === "function") {
+        compareFunction = function(eventObj) {
+          for (var i = 0; i < elements.length; i++) {
+            if ((this === undefined || eventObj.target === elements[i]) && eventObj.callback === callback) {
+              return true;
+            }
+          }
+          return false;
+        };
+      }
+      else {
+        compareFunction = function(eventObj) {
+          for (var i = 0; i < elements.length; i++) {
+            if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector) {
+              return true;
+            }
+          }
+          return false;
+        };
+      }
+      eventsBucket.removeEvent(compareFunction);
+    };
+
+    this.unbindEventWithSelectorAndCallback = function(selector, callback) {
+      var elements = utils.toElementsArray(this);
+      eventsBucket.removeEvent(function(eventObj) {
+          for (var i = 0; i < elements.length; i++) {
+            if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector && eventObj.callback === callback) {
+              return true;
+            }
+          }
+          return false;
+      });
+    };
+
+    return this;
+  };
+
+
+  /**
+   * @constructor
+   * Processes 'arrive' events
+   */
+  var ArriveEvents = function() {
+    // Default options for 'arrive' event
+    var arriveDefaultOptions = {
+      fireOnAttributesModification: false,
+      onceOnly: false,
+      existing: false
+    };
+
+    function getArriveObserverConfig(options) {
+      var config = {
+        attributes: false,
+        childList: true,
+        subtree: true
+      };
+
+      if (options.fireOnAttributesModification) {
+        config.attributes = true;
+      }
+
+      return config;
+    }
+
+    function onArriveMutation(mutations, registrationData) {
+      mutations.forEach(function( mutation ) {
+        var newNodes    = mutation.addedNodes,
+            targetNode = mutation.target,
+            callbacksToBeCalled = [],
+            node;
+
+        // If new nodes are added
+        if( newNodes !== null && newNodes.length > 0 ) {
+          utils.checkChildNodesRecursively(newNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
+        }
+        else if (mutation.type === "attributes") {
+          if (nodeMatchFunc(targetNode, registrationData, callbacksToBeCalled)) {
+            callbacksToBeCalled.push({ callback: registrationData.callback, elem: targetNode });
+          }
+        }
+
+        utils.callCallbacks(callbacksToBeCalled, registrationData);
+      });
+    }
+
+    function nodeMatchFunc(node, registrationData, callbacksToBeCalled) {
+      // check a single node to see if it matches the selector
+      if (utils.matchesSelector(node, registrationData.selector)) {
+        if(node._id === undefined) {
+          node._id = arriveUniqueId++;
+        }
+        // make sure the arrive event is not already fired for the element
+        if (registrationData.firedElems.indexOf(node._id) == -1) {
+          registrationData.firedElems.push(node._id);
+
+          return true;
+        }
+      }
+
+      return false;
+    }
+
+    arriveEvents = new MutationEvents(getArriveObserverConfig, onArriveMutation);
+
+    var mutationBindEvent = arriveEvents.bindEvent;
+
+    // override bindEvent function
+    arriveEvents.bindEvent = function(selector, options, callback) {
+
+      if (typeof callback === "undefined") {
+        callback = options;
+        options = arriveDefaultOptions;
+      } else {
+        options = utils.mergeArrays(arriveDefaultOptions, options);
+      }
+
+      var elements = utils.toElementsArray(this);
+
+      if (options.existing) {
+        var existing = [];
+
+        for (var i = 0; i < elements.length; i++) {
+          var nodes = elements[i].querySelectorAll(selector);
+          for (var j = 0; j < nodes.length; j++) {
+            existing.push({ callback: callback, elem: nodes[j] });
+          }
+        }
+
+        // no need to bind event if the callback has to be fired only once and we have already found the element
+        if (options.onceOnly && existing.length) {
+          return callback.call(existing[0].elem, existing[0].elem);
+        }
+
+        setTimeout(utils.callCallbacks, 1, existing);
+      }
+
+      mutationBindEvent.call(this, selector, options, callback);
+    };
+
+    return arriveEvents;
+  };
+
+
+  /**
+   * @constructor
+   * Processes 'leave' events
+   */
+  var LeaveEvents = function() {
+    // Default options for 'leave' event
+    var leaveDefaultOptions = {};
+
+    function getLeaveObserverConfig() {
+      var config = {
+        childList: true,
+        subtree: true
+      };
+
+      return config;
+    }
+
+    function onLeaveMutation(mutations, registrationData) {
+      mutations.forEach(function( mutation ) {
+        var removedNodes  = mutation.removedNodes,
+            callbacksToBeCalled = [];
+
+        if( removedNodes !== null && removedNodes.length > 0 ) {
+          utils.checkChildNodesRecursively(removedNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
+        }
+
+        utils.callCallbacks(callbacksToBeCalled, registrationData);
+      });
+    }
+
+    function nodeMatchFunc(node, registrationData) {
+      return utils.matchesSelector(node, registrationData.selector);
+    }
+
+    leaveEvents = new MutationEvents(getLeaveObserverConfig, onLeaveMutation);
+
+    var mutationBindEvent = leaveEvents.bindEvent;
+
+    // override bindEvent function
+    leaveEvents.bindEvent = function(selector, options, callback) {
+
+      if (typeof callback === "undefined") {
+        callback = options;
+        options = leaveDefaultOptions;
+      } else {
+        options = utils.mergeArrays(leaveDefaultOptions, options);
+      }
+
+      mutationBindEvent.call(this, selector, options, callback);
+    };
+
+    return leaveEvents;
+  };
+
+
+  var arriveEvents = new ArriveEvents(),
+      leaveEvents  = new LeaveEvents();
+
+  function exposeUnbindApi(eventObj, exposeTo, funcName) {
+    // expose unbind function with function overriding
+    utils.addMethod(exposeTo, funcName, eventObj.unbindEvent);
+    utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorOrCallback);
+    utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorAndCallback);
+  }
+
+  /*** expose APIs ***/
+  function exposeApi(exposeTo) {
+    exposeTo.arrive = arriveEvents.bindEvent;
+    exposeUnbindApi(arriveEvents, exposeTo, "unbindArrive");
+
+    exposeTo.leave = leaveEvents.bindEvent;
+    exposeUnbindApi(leaveEvents, exposeTo, "unbindLeave");
+  }
+
+  if ($) {
+    exposeApi($.fn);
+  }
+  exposeApi(HTMLElement.prototype);
+  exposeApi(NodeList.prototype);
+  exposeApi(HTMLCollection.prototype);
+  exposeApi(HTMLDocument.prototype);
+  exposeApi(Window.prototype);
+
+  var Arrive = {};
+  // expose functions to unbind all arrive/leave events
+  exposeUnbindApi(arriveEvents, Arrive, "unbindAllArrive");
+  exposeUnbindApi(leaveEvents, Arrive, "unbindAllLeave");
+
+  return Arrive;
+
+})(window, typeof jQuery === 'undefined' ? null : jQuery, undefined);

File diff ditekan karena terlalu besar
+ 9 - 0
js/arrive.min.js


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini