diff options
| -rw-r--r-- | src/Angular.js | 6 | ||||
| -rw-r--r-- | src/jqLite.js | 65 | ||||
| -rw-r--r-- | test/jqLiteSpec.js | 27 |
3 files changed, 89 insertions, 9 deletions
diff --git a/src/Angular.js b/src/Angular.js index 367a7752..407fc263 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -985,8 +985,12 @@ function bindJQuery(){ if (jQuery) { jqLite = jQuery; extend(jQuery.fn, { - scope: JQLitePrototype.scope + scope: JQLitePrototype.scope, + inheritedData: JQLitePrototype.inheritedData }); + JQLitePatchJQueryRemove('remove', true); + JQLitePatchJQueryRemove('empty'); + JQLitePatchJQueryRemove('html'); } else { jqLite = jqLiteWrap; } diff --git a/src/jqLite.js b/src/jqLite.js index 13bd55ba..ae540e89 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -99,6 +99,46 @@ function camelCase(name) { } ///////////////////////////////////////////// +// jQuery mutation patch +///////////////////////////////////////////// + +function JQLitePatchJQueryRemove(name, dispatchThis) { + var originalJqFn = jQuery.fn[name]; + originalJqFn = originalJqFn.$original || originalJqFn; + removePatch.$original = originalJqFn; + jQuery.fn[name] = removePatch; + + function removePatch() { + var list = [this], + fireEvent = dispatchThis, + set, setIndex, setLength, + element, childIndex, childLength, children, + fns, data; + + while(list.length) { + set = list.shift(); + for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) { + element = jqLite(set[setIndex]); + if (fireEvent) { + data = element.data('events'); + if ( (fns = data && data.$destroy) ) { + forEach(fns, function(fn){ + fn.handler(); + }); + } + } else { + fireEvent = !fireEvent; + } + for(childIndex = 0, childLength = (children = element.children()).length; childIndex < childLength; childIndex++) { + list.push(jQuery(children[childIndex])); + } + } + } + return originalJqFn.apply(this, arguments); + } +} + +///////////////////////////////////////////// function jqLiteWrap(element) { if (isString(element) && element.charAt(0) != '<') { throw new Error('selectors not implemented'); @@ -137,9 +177,15 @@ function JQLiteRemoveData(element) { var cacheId = element[jqName], cache = jqCache[cacheId]; if (cache) { - forEach(cache.bind || {}, function(fn, type){ - removeEventListenerFn(element, type, fn); - }); + if (cache.bind) { + forEach(cache.bind, function(fn, type){ + if (type == '$destroy') { + fn({}); + } else { + removeEventListenerFn(element, type, fn); + } + }); + } delete jqCache[cacheId]; element[jqName] = undefined; // ie does not allow deletion of attributes on elements. } @@ -241,13 +287,16 @@ var SPECIAL_ATTR = makeMap("multiple,selected,checked,disabled,readonly,required forEach({ data: JQLiteData, + inheritedData: function(element, name, value) { + element = jqLite(element); + while (element.length) { + if (value = element.data(name)) return value; + element = element.parent(); + } + }, scope: function(element) { - var scope; - while (element && !(scope = jqLite(element).data($$scope))) { - element = element.parentNode; - } - return scope; + return jqLite(element).inheritedData($$scope); }, removeAttr: function(element,name) { diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index 24795331..f66b6244 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -83,6 +83,33 @@ describe('jqLite', function(){ }); + describe('inheritedData', function() { + + it('should retrieve data attached to the current element', function() { + var element = jqLite('<i>foo</i>'); + element.data('myData', 'abc'); + expect(element.inheritedData('myData')).toBe('abc'); + dealoc(element); + }); + + + it('should walk up the dom to find data', function() { + var element = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>'); + var deepChild = jqLite(element[0].getElementsByTagName('b')[0]); + element.data('myData', 'abc'); + expect(deepChild.inheritedData('myData')).toBe('abc'); + dealoc(element); + }); + + + it('should return undefined when no data was found', function() { + var element = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>'); + var deepChild = jqLite(element[0].getElementsByTagName('b')[0]); + expect(deepChild.inheritedData('myData')).toBeFalsy(); + dealoc(element); + }); + }); + describe('scope', function() { it('should retrieve scope attached to the current element', function() { var element = jqLite('<i>foo</i>'); |
