Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use MutationObserver to maintain custom event bindings, bug fixes #20

Merged
merged 4 commits into from
Oct 23, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 69 additions & 42 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,24 +37,25 @@
value ? this.add(name) : this.remove(name);
};
})();

(function(){

// attribute bindings

var bindAttrs = function(inAttributes) {
var attrs = this.boundAttributes = [];
if (inAttributes) {
var bindables = inAttributes.value.split(",");
bindables.forEach(function(a) {
attrs.push(a.trim());
a = a.trim();
attrs.push(a);
bindProperty.call(this, a, this[a]);
}, this);
}
};

// event bindings

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

// property bindings

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

var squelchSideEffects = false;

var setPropertySilently = function(inName, inValue) {
Expand All @@ -104,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 @@ -120,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 @@ -179,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 @@ -188,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 @@ -220,7 +224,7 @@
};

// decorate HTMLElementElement with toolkit API

HTMLElementElement.prototype.component = function(inUber) {
var attributes = this.element.attributes;
this.lifecycle({
Expand All @@ -237,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 @@ -246,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 @@ -269,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 @@ -282,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 @@ -335,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 @@ -356,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 @@ -384,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 @@ -397,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