silverstripe-framework/thirdparty/jquery-concrete/src/jquery.concrete.ctors.js
Ingo Schommer dca8c0cb6f merging
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@92557 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-11-21 02:33:06 +00:00

103 lines
3.1 KiB
JavaScript

(function($) {
/* Add the methods to handle constructor & destructor binding to the Namespace class */
$.concrete.Namespace.addMethods({
bind_condesc: function(selector, name, func) {
var ctors = this.store.ctors || (this.store.ctors = $.concrete.RuleList()) ;
var rule;
for (var i = 0 ; i < ctors.length; i++) {
if (ctors[i].selector.selector == selector.selector) {
rule = ctors[i]; break;
}
}
if (!rule) {
rule = ctors.addRule(selector, 'ctors');
}
rule[name] = func;
if (!ctors[name+'proxy']) {
var one = this.one('ctors', name);
var namespace = this;
var proxy = function(els, i, func) {
var j = els.length;
while (j--) {
var el = els[j];
var tmp_i = el.i, tmp_f = el.f;
el.i = i; el.f = one;
try { func.call(namespace.$(el)); }
catch(e) { el.i = tmp_i; el.f = tmp_f; }
}
}
ctors[name+'proxy'] = proxy;
}
}
});
$.concrete.Namespace.addHandler({
order: 30,
bind: function(selector, k, v) {
if ($.isFunction(v) && (k == 'onmatch' || k == 'onunmatch')) {
this.bind_condesc(selector, k, v);
return true;
}
}
});
/**
* Finds all the elements that now match a different rule (or have been removed) and call onmatch on onunmatch as appropriate
*
* Because this has to scan the DOM, and is therefore fairly slow, this is normally triggered off a short timeout, so that
* a series of DOM manipulations will only trigger this once.
*
* The downside of this is that things like:
* $('#foo').addClass('tabs'); $('#foo').tabFunctionBar();
* won't work.
*/
$(document).bind('DOMMaybeChanged', function(){
// For every namespace
for (var k in $.concrete.namespaces) {
// That has constructors or destructors
var ctors = $.concrete.namespaces[k].store.ctors;
if (ctors) {
// Keep a record of elements that have matched already
var matched = $([]), match, add, rem;
// Stepping through each selector from most to least specific
var j = ctors.length;
while (j--) {
// Build some quick-acccess variables
var sel = ctors[j].selector.selector, ctor = ctors[j].onmatch; dtor = ctors[j].onunmatch;
// Get the list of elements that match this selector, that haven't yet matched a more specific selector
res = add = $(sel).not(matched);
// If this selector has a list of elements it matched against last time
if (ctors[j].cache) {
// Find the ones that are extra this time
add = res.not(ctors[j].cache);
// Find the ones that are gone this time
rem = ctors[j].cache.not(res);
// And call the desctructor on them
if (rem.length && dtor) ctors.onunmatchproxy(rem, j, dtor);
}
// Call the constructor on the newly matched ones
if (add.length && ctor) ctors.onmatchproxy(add, j, ctor);
// Add these matched ones to the list tracking all elements matched so far
matched = matched.add(res);
// And remember this list of matching elements again this selector, so next matching we can find the unmatched ones
ctors[j].cache = res;
}
}
}
})
})(jQuery);