(function($){ /** What to call to run a function 'soon'. Normally setTimeout, but for syncronous mode we override so soon === now */ var runSoon = window.setTimeout; /** The timer handle for the asyncronous matching call */ var check_id = null; /** Fire the change event. Only fires on the document node, so bind to that */ var triggerEvent = function() { $(document).triggerHandler('DOMMaybeChanged'); check_id = null; } $.extend($.concrete, { /** * Make onmatch and onunmatch work in synchronous mode - that is, new elements will be detected immediately after * the DOM manipulation that made them match. This is only really useful for during testing, since it's pretty slow * (otherwise we'd make it the default). */ synchronous_mode: function() { if (check_id) clearTimeout(check_id); check_id = null; runSoon = function(func, delay){ func.call(this); return null; } }, /** * Trigger onmatch and onunmatch now - usefull for after DOM manipulation by methods other than through jQuery. * Called automatically on document.ready */ triggerMatching: function() { matching(); } }); function registerMutateFunction() { $.each(arguments, function(i,func){ var old = $.fn[func]; $.fn[func] = function() { var rv = old.apply(this, arguments); if (!check_id) check_id = runSoon(triggerEvent, 100); return rv; } }) } function registerSetterGetterFunction() { $.each(arguments, function(i,func){ var old = $.fn[func]; $.fn[func] = function(a, b) { var rv = old.apply(this, arguments); if (!check_id && (b !== undefined || typeof a != 'string')) check_id = runSoon(triggerEvent, 100); return rv; } }) } // Register core DOM manipulation methods registerMutateFunction('append', 'prepend', 'after', 'before', 'wrap', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove'); registerSetterGetterFunction('attr'); // And on DOM ready, trigger matching once $(function(){ triggerEvent(); }) })(jQuery);