packages feed

miso-0.21.2.0: jsbits/delegate.js

window.oldCallbacks = [];
window.currentCallbacks = [];

/* Callbacks in ghcjs need to be released. With this function one can register
   callbacks that should be released right before diffing.
*/
window.registerCallback = function registerCallback(cb) {
    currentCallbacks.push(cb);
};

/* Swaps out the new calbacks for old callbacks.
The old callbacks should be cleared once the new callbacks have replaced them.
*/
window.swapCallbacks = function swapCallbacks() {
  oldCallbacks = currentCallbacks;
  currentCallbacks = [];
};

/* This releases the old callbacks. */
window.releaseCallbacks = function releaseCallbacks() {
    for (var i in oldCallbacks)
      h$release(oldCallbacks[i]);

    oldCallbacks = [];
};

/* event delegation algorithm */
window.delegate = function delegate(mountPointElement, events, getVTree) {
    for (var event in events) {
	  mountPointElement.addEventListener(events[event][0], function(e) {
        getVTree(function (obj) {
          delegateEvent ( e
                          , obj
                          , buildTargetToElement(mountPointElement, e.target)
                          , []
                        );
        });
	     }, events[event][1]);
    }
};

/* Accumulate parent stack as well for propagation */
window.delegateEvent = function delegateEvent (event, obj, stack, parentStack) {

    /* base case, not found */
    if (!stack.length) return;

    /* stack not length 1, recurse */
    else if (stack.length > 1) {
      if (obj.domRef === stack[0]) parentStack.unshift(obj);
	for (var o = 0; o < obj.children.length; o++) {
          if (obj.children[o].type === "vtext") continue;
          delegateEvent ( event
                        , obj.children[o]
                        , stack.slice(1)
                        , parentStack
			                  );
       }
    }

    /* stack.length == 1 */
    else {
	if (obj.domRef === stack[0]) {
	    var eventObj = obj.events[event.type];
	    if (eventObj) {
		var options = eventObj.options;
		if (options.preventDefault)
		    event.preventDefault();
		eventObj.runEvent(event);
		if (!options.stopPropagation)
		    propogateWhileAble (parentStack, event);
	    } else {
		 /* still propagate to parent handlers even if event not defined */
 		 propogateWhileAble (parentStack, event);
	      }
	}
    }
};

window.buildTargetToElement = function buildTargetToElement (element, target) {
    var stack = [];
    while (element !== target) {
      stack.unshift (target);
      target = target.parentNode;
    }
    return stack;
};

window.propogateWhileAble = function propogateWhileAble (parentStack, event) {
  for (var i = 0; i < parentStack.length; i++) {
    if (parentStack[i].events[event.type]) {
      var eventObj = parentStack[i].events[event.type],
          options = eventObj.options;
        if (options.preventDefault) event.preventDefault();
        eventObj.runEvent(event);
  	if (options.stopPropagation) break;
    }
  }
};

/* Walks down obj following the path described by `at`, then filters primitive
 values (string, numbers and booleans)*/
window.objectToJSON = function objectToJSON (at, obj) {
  /* If at is of type [[MisoString]] */
  if (typeof at[0] == "object") {
    var ret = [];
    for (var i = 0; i < at.length; i++)
      ret.push(objectToJSON(at[i], obj));
    return (ret);
  }

  for (var i in at) obj = obj[at[i]];

  /* If obj is a list-like object */
  if (obj instanceof Array) {
    var newObj = [];
    for (var i = 0; i < obj.length; i++)
      newObj.push(objectToJSON([], obj[i]));
    return (newObj);
  }

  /* If obj is a non-list-like object */
  var newObj = {};
    for (var i in obj){
    /* bug in safari, throws TypeError if the following fields are referenced on a checkbox */
    /* https://stackoverflow.com/a/25569117/453261 */
    /* https://html.spec.whatwg.org/multipage/input.html#do-not-apply */
    if (obj['type'] == "checkbox" && (i === "selectionDirection" || i === "selectionStart" || i === "selectionEnd"))
      continue;
    if (typeof obj[i] == "string" || typeof obj[i] == "number" || typeof obj[i] == "boolean")
      newObj[i] = obj[i];
    }
    return newObj;
};