Skip to content

Commit

Permalink
Merge pull request #20 from sjmiles/e334f1293f394165dd1e53e7527bc624f…
Browse files Browse the repository at this point in the history
…99ec4f7

use MutationObserver to maintain custom event bindings, bug fixes
  • Loading branch information
frankiefu committed Oct 23, 2012
2 parents 1b54847 + e334f12 commit c073e71
Showing 1 changed file with 67 additions and 41 deletions.
108 changes: 67 additions & 41 deletions src/g-component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
PROPERTY_CHANGED_SUFFIX: "Changed",
CUSTOM_EVENT_PREFIX: "at"
};
// polyfill for DOMTokenList features: list of classes in add/remove;

// polyfill for DOMTokenList features: list of classes in add/remove;
// enable method.
(function() {
'use strict';
Expand All @@ -37,11 +37,11 @@
value ? this.add(name) : this.remove(name);
};
})();

(function(){

// attribute bindings

var bindAttrs = function(inAttributes) {
var attrs = this.boundAttributes = [];
if (inAttributes) {
Expand All @@ -53,9 +53,9 @@
}, this);
}
};

// event bindings

var bindEvents = function(inEvents) {
if (inEvents) {
var bindables = inEvents.value.split(",");
Expand All @@ -70,7 +70,7 @@
}, this);
}
};

// property bindings

var propertyChanged = function(inName, inOld) {
Expand All @@ -88,7 +88,7 @@
}
};
};

var squelchSideEffects = false;

var setPropertySilently = function(inName, inValue) {
Expand All @@ -105,6 +105,7 @@
// set default value in a property already bound via attrs
setPropertySilently.call(this, inName, value);
} else {
console.log('binding', inName, this)
var value = inValue;
var sideEffect = sideEffectFactory(inName);
Object.defineProperty(this, inName, {
Expand All @@ -121,30 +122,32 @@
});
}
};

var bindProperties = function(inProperties) {
if (inProperties) {
Object.keys(inProperties).forEach(function(n) {
bindProperty.call(this, n, inProperties[n]);
}, this);
}
};

var deref = function(inNode) {
return inNode && (inNode.baby || inNode);
};

var establishNodeReferences = function(inRoot) {
this.$ = this.$ || {};
// search the LOCAL tree
var nodes = ShadowDOM.localQueryAll(inRoot, "[id]");
Array.prototype.forEach.call(nodes, function(n) {
this.$[n.id] = deref(n);
}, this);
if (inRoot) {
var nodes = ShadowDOM.localQueryAll(inRoot, "[id]");
Array.prototype.forEach.call(nodes, function(n) {
this.$[n.id] = deref(n);
}, this);
}
};

// attribute mutations

var deserializeValue = function(inValue) {
switch (inValue) {
case "":
Expand Down Expand Up @@ -180,7 +183,7 @@
propertyChanged.call(this, c.name, c.old);
}, this);
};

var attributeChanged = function(inName) {
var value = this.getAttribute(inName);
this[inName] = deserializeValue(value);
Expand All @@ -189,7 +192,7 @@
var handleMutations = function(inMxns) {
inMxns.forEach(function(inMxn) {
var name = inMxn.attributeName;
if (this.boundAttributes[name]) {
if (this.boundAttributes.indexOf(name) >= 0) {
attributeChanged.call(this, name);
}
}, this);
Expand Down Expand Up @@ -221,7 +224,7 @@
};

// decorate HTMLElementElement with toolkit API

HTMLElementElement.prototype.component = function(inUber) {
var attributes = this.element.attributes;
this.lifecycle({
Expand All @@ -238,7 +241,7 @@
this.attrObserver = new AttrObserver(this);
}
});
var p = inUber.prototype;
var p = inUber.prototype || {};
// attach some API
// TODO(sjmiles): this is probably not the best way to do this;
// probably better to insert another link in the prototype chain
Expand All @@ -247,11 +250,11 @@
// install our prototype
this.generatedConstructor.prototype = p;
};

// utility methods

// job

var job = function(inJobName, inJob, inWait) {
var name = inJobName || ("__" + Math.random());
job.stop(name);
Expand All @@ -270,8 +273,8 @@
job._jobs = {};

// target finding
findDistributedTarget = function(inTarget, inItems) {

var findDistributedTarget = function(inTarget, inItems) {
// find ancestor of target (including himself) that
// is in our item list, if any
var n = inTarget;
Expand All @@ -283,19 +286,19 @@
n = n.parentNode;
}
};
// collect utils

// collect utils

var utils = {
job: job,
findDistributedTarget: findDistributedTarget
};

// code below provides a shim for declarative event handlers
// (aka 'x', as in onclick="x('click')")
// it's only really for evaluating syntax, and not
// it's only really for evaluating syntax, and not
// a real solution

var nodeIterator = function(inNodes, inFn) {
if (inNodes) {
for (var i=0, n; (n=inNodes[i]); i++) {
Expand Down Expand Up @@ -336,15 +339,15 @@
// experimental event handler for mapping events to component instances
// publish handler globally, make name as small as possible since
// this is ideally an invisible helper API

x = function(inHandler) {
var owner = findOwner(event.currentTarget);
//console.log(inHandler, owner, event);
if (owner && owner[inHandler]) {
owner[inHandler](event);
}
};

// newer experimental event handler

var findController = function(inNode) {
Expand All @@ -357,22 +360,26 @@
n = n.parentNode || n.host;
}
};

_ = function(inHandlerName) {
var controller = findController(event.currentTarget);
//console.log(inHandler, owner, event);
if (controller && controller[inHandlerName]) {
controller[inHandlerName](event);
}
};

// automagic event mapping

var bindCustomEvent = function(inNode, inEventName, inHandler) {
//console.log(inEventName, inHandler);
inNode.addEventListener(inEventName, function() {
_(inHandler);
});
var h = inNode.__athandlers = inNode.__athandlers || {};
if (!h[inEventName]) {
console.log("bindCustomEvent:", inEventName, inHandler, inNode);
h[inEventName] = function() {
_(inHandler);
};
inNode.addEventListener(inEventName, h[inEventName]);
}
};

var bindCustomEvents = function(inNode) {
Expand All @@ -385,9 +392,9 @@
}
}
};

// TODO(sjmiles): improper tree walking (?)
var bindAllCustomEvents = function(inNode) {
var _bindAllCustomEvents = function(inNode) {
bindCustomEvents(inNode);
if (inNode.childNodes) {
for (var i=0, c; c=deref(inNode.childNodes[i]); i++) {
Expand All @@ -398,6 +405,25 @@
}
};

var __bindAllCustomEvents = function(inNode) {
_bindAllCustomEvents(inNode);
};

var eventsObserver = function(inNode) {
new WebKitMutationObserver(__bindAllCustomEvents.bind(this, inNode))
.observe(inNode, {
childList: true,
subTree: true
});
};

var bindAllCustomEvents = function(inNode) {
if (inNode) {
_bindAllCustomEvents(inNode);
eventsObserver(inNode);
}
};

})();
</script>
</element>
Expand Down

0 comments on commit c073e71

Please sign in to comment.