diff --git a/src/jqLite.js b/src/jqLite.js index 67b6137d4aed..d255845ef62d 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -37,6 +37,7 @@ * - [clone()](http://api.jquery.com/clone/) * - [css()](http://api.jquery.com/css/) * - [data()](http://api.jquery.com/data/) + * - [eq()](http://api.jquery.com/eq/) * - [hasClass()](http://api.jquery.com/hasClass/) * - [parent()](http://api.jquery.com/parent/) * - [remove()](http://api.jquery.com/remove/) @@ -46,7 +47,7 @@ * - [replaceWith()](http://api.jquery.com/replaceWith/) * - [text()](http://api.jquery.com/text/) * - [trigger()](http://api.jquery.com/trigger/) - * - [eq()](http://api.jquery.com/eq/) + * - [unbind()](http://api.jquery.com/unbind/) * * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite: * @@ -401,6 +402,25 @@ forEach({ }); }, + unbind: function(element, type, fn) { + var bind = JQLiteData(element, 'bind'); + if (!bind) return; //no listeners registered + + if (isUndefined(type)) { + forEach(bind, function(eventHandler, type) { + removeEventListenerFn(element, type, eventHandler); + delete bind[type]; + }); + } else { + if (isUndefined(fn)) { + removeEventListenerFn(element, type, bind[type]); + delete bind[type]; + } else { + angularArray.remove(bind[type].fns, fn); + } + } + }, + replaceWith: function(element, replaceNode) { var index, parent = element.parentNode; JQLiteDealoc(element); diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index 6578022c07b7..0ebb17170c2d 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -450,6 +450,102 @@ describe('jqLite', function(){ }); + describe('unbind', function() { + it('should do nothing when no listener was registered with bound', function() { + var aElem = jqLite(a); + + aElem.unbind(); + aElem.unbind('click'); + aElem.unbind('click', function() {}); + }); + + + it('should deregister all listeners', function() { + var aElem = jqLite(a), + clickSpy = jasmine.createSpy('click'), + mouseoverSpy = jasmine.createSpy('mouseover'); + + aElem.bind('click', clickSpy); + aElem.bind('mouseover', mouseoverSpy); + + browserTrigger(a, 'click'); + expect(clickSpy).toHaveBeenCalledOnce(); + browserTrigger(a, 'mouseover'); + expect(mouseoverSpy).toHaveBeenCalledOnce(); + + clickSpy.reset(); + mouseoverSpy.reset(); + + aElem.unbind(); + + browserTrigger(a, 'click'); + expect(clickSpy).not.toHaveBeenCalled(); + browserTrigger(a, 'mouseover'); + expect(mouseoverSpy).not.toHaveBeenCalled(); + }); + + + it('should deregister listeners for specific type', function() { + var aElem = jqLite(a), + clickSpy = jasmine.createSpy('click'), + mouseoverSpy = jasmine.createSpy('mouseover'); + + aElem.bind('click', clickSpy); + aElem.bind('mouseover', mouseoverSpy); + + browserTrigger(a, 'click'); + expect(clickSpy).toHaveBeenCalledOnce(); + browserTrigger(a, 'mouseover'); + expect(mouseoverSpy).toHaveBeenCalledOnce(); + + clickSpy.reset(); + mouseoverSpy.reset(); + + aElem.unbind('click'); + + browserTrigger(a, 'click'); + expect(clickSpy).not.toHaveBeenCalled(); + browserTrigger(a, 'mouseover'); + expect(mouseoverSpy).toHaveBeenCalledOnce(); + + mouseoverSpy.reset(); + + aElem.unbind('mouseover'); + browserTrigger(a, 'mouseover'); + expect(mouseoverSpy).not.toHaveBeenCalled(); + }); + + + it('should deregister specific listener', function() { + var aElem = jqLite(a), + clickSpy1 = jasmine.createSpy('click1'), + clickSpy2 = jasmine.createSpy('click2'); + + aElem.bind('click', clickSpy1); + aElem.bind('click', clickSpy2); + + browserTrigger(a, 'click'); + expect(clickSpy1).toHaveBeenCalledOnce(); + expect(clickSpy2).toHaveBeenCalledOnce(); + + clickSpy1.reset(); + clickSpy2.reset(); + + aElem.unbind('click', clickSpy1); + + browserTrigger(a, 'click'); + expect(clickSpy1).not.toHaveBeenCalled(); + expect(clickSpy2).toHaveBeenCalledOnce(); + + clickSpy2.reset(); + + aElem.unbind('click', clickSpy2); + browserTrigger(a, 'click'); + expect(clickSpy2).not.toHaveBeenCalled(); + }); + }); + + describe('replaceWith', function(){ it('should replaceWith', function(){ var root = jqLite('