Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(jqLite): switch bind/unbind to more recent jQuery on/off
Browse files Browse the repository at this point in the history
jQuery switched to a completely new event binding implementation as of
1.7.0, centering around on/off methods instead of previous bind/unbind.
This patch makes jqLite match this implementation while still supporting
previous bind/unbind methods.
  • Loading branch information
mgol authored and petebacondarwin committed Jun 19, 2013
1 parent 0bfa293 commit f1b94b4
Show file tree
Hide file tree
Showing 30 changed files with 154 additions and 119 deletions.
2 changes: 1 addition & 1 deletion docs/components/angular-bootstrap/bootstrap-prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
}]);
if (attrs.ngEmbedApp) modules.push(attrs.ngEmbedApp);

element.bind('click', function(event) {
element.on('click', function(event) {
if (event.target.attributes.getNamedItem('ng-click')) {
event.preventDefault();
}
Expand Down
12 changes: 6 additions & 6 deletions docs/components/angular-bootstrap/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ directive.dropdownToggle =
close && close();
});

element.parent().bind('click', function(event) {
element.parent().on('click', function(event) {
close && close();
});

element.bind('click', function(event) {
element.on('click', function(event) {
event.preventDefault();
event.stopPropagation();

Expand All @@ -35,13 +35,13 @@ directive.dropdownToggle =
close = function (event) {
event && event.preventDefault();
event && event.stopPropagation();
$document.unbind('click', close);
$document.off('click', close);
element.parent().removeClass('open');
close = null;
openElement = null;
}

$document.bind('click', close);
$document.on('click', close);
}
});
}
Expand Down Expand Up @@ -161,7 +161,7 @@ directive.tabbable = function() {
}

navTabs.append(li);
li.bind('click', function(event) {
li.on('click', function(event) {
event.preventDefault();
event.stopPropagation();
if (ngModel.$setViewValue) {
Expand Down Expand Up @@ -330,7 +330,7 @@ directive.tabPane = function() {
require: '^tabbable',
restrict: 'C',
link: function(scope, element, attrs, tabsCtrl) {
element.bind('$remove', tabsCtrl.addPane(element, attrs));
element.on('$remove', tabsCtrl.addPane(element, attrs));
}
};
};
Expand Down
6 changes: 3 additions & 3 deletions docs/content/guide/compiler.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
backgroundColor: 'lightgrey',
cursor: 'pointer'
});
element.bind('mousedown', function(event) {
element.on('mousedown', function(event) {
// Prevent default dragging of selected content
event.preventDefault();
startX = event.screenX - x;
startY = event.screenY - y;
$document.bind('mousemove', mousemove);
$document.bind('mouseup', mouseup);
$document.on('mousemove', mousemove);
$document.on('mouseup', mouseup);
});

function mousemove(event) {
Expand Down
2 changes: 1 addition & 1 deletion docs/content/guide/concepts.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ in HTML.
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
elm.on('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
Expand Down
4 changes: 2 additions & 2 deletions docs/content/guide/dev_guide.services.$location.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ In this examples we use `<base href="/base/index.html" />`
input = angular.element('<input type="text">').val(browser.url()),
delay;

input.bind('keypress keyup keydown', function() {
input.on('keypress keyup keydown', function() {
if (!delay) {
delay = setTimeout(fireUrlChange, 250);
}
Expand All @@ -469,7 +469,7 @@ In this examples we use `<base href="/base/index.html" />`
};
});
}]);
root.bind('click', function(e) {
root.on('click', function(e) {
e.stopPropagation();
});
}
Expand Down
4 changes: 2 additions & 2 deletions docs/content/guide/directive.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ In this example we will build a directive that displays the current time.

// listen on DOM destroy (removal) event, and cancel the next UI update
// to prevent updating time after the DOM element was removed.
element.bind('$destroy', function() {
element.on('$destroy', function() {
$timeout.cancel(timeoutId);
});

Expand Down Expand Up @@ -687,7 +687,7 @@ Following is an example of building a reusable widget.
opened = true;

// Clicking on title should open/close the zippy
title.bind('click', toggle);
title.on('click', toggle);

// Toggle the closed/opened state
function toggle() {
Expand Down
2 changes: 1 addition & 1 deletion docs/content/guide/forms.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ The following example shows how to add two-way data-binding to contentEditable e
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
elm.on('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
Expand Down
6 changes: 3 additions & 3 deletions docs/src/templates/js/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ docsApp.serviceFactory.docsSearch = ['$rootScope','lunrSearch', 'NG_PAGES',
docsApp.directive.focused = function($timeout) {
return function(scope, element, attrs) {
element[0].focus();
element.bind('focus', function() {
element.on('focus', function() {
scope.$apply(attrs.focused + '=true');
});
element.bind('blur', function() {
element.on('blur', function() {
// have to use $timeout, so that we close the drop-down after the user clicks,
// otherwise when the user clicks we process the closing before we process the click.
$timeout(function() {
Expand Down Expand Up @@ -610,7 +610,7 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
$location.path('/api').replace();
}
// bind escape to hash reset callback
angular.element(window).bind('keydown', function(e) {
angular.element(window).on('keydown', function(e) {
if (e.keyCode === 27) {
$scope.$apply(function() {
$scope.subpage = false;
Expand Down
2 changes: 1 addition & 1 deletion src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ function trim(value) {
function isElement(node) {
return node &&
(node.nodeName // we are a direct element
|| (node.bind && node.find)); // we have a bind and find method part of jQuery API
|| (node.on && node.find)); // we have an on and find method part of jQuery API
}

/**
Expand Down
39 changes: 25 additions & 14 deletions src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* - [after()](http://api.jquery.com/after/)
* - [append()](http://api.jquery.com/append/)
* - [attr()](http://api.jquery.com/attr/)
* - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
* - [bind()](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
* - [children()](http://api.jquery.com/children/) - Does not support selectors
* - [clone()](http://api.jquery.com/clone/)
* - [contents()](http://api.jquery.com/contents/)
Expand All @@ -43,6 +43,8 @@
* - [hasClass()](http://api.jquery.com/hasClass/)
* - [html()](http://api.jquery.com/html/)
* - [next()](http://api.jquery.com/next/) - Does not support selectors
* - [on()](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
* - [off()](http://api.jquery.com/off/) - Does not support namespaces or selectors
* - [parent()](http://api.jquery.com/parent/) - Does not support selectors
* - [prepend()](http://api.jquery.com/prepend/)
* - [prop()](http://api.jquery.com/prop/)
Expand All @@ -55,7 +57,7 @@
* - [text()](http://api.jquery.com/text/)
* - [toggleClass()](http://api.jquery.com/toggleClass/)
* - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
* - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
* - [unbind()](http://api.jquery.com/off/) - Does not support namespaces
* - [val()](http://api.jquery.com/val/)
* - [wrap()](http://api.jquery.com/wrap/)
*
Expand Down Expand Up @@ -90,6 +92,7 @@ function jqNextId() { return ++jqId; }

var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
var MOZ_HACK_REGEXP = /^moz([A-Z])/;
var jqLiteError = minErr('jqLite');

/**
* Converts snake_case to camelCase.
Expand Down Expand Up @@ -153,7 +156,7 @@ function JQLite(element) {
}
if (!(this instanceof JQLite)) {
if (isString(element) && element.charAt(0) != '<') {
throw minErr('jqLite')('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
throw jqLiteError('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
}
return new JQLite(element);
}
Expand Down Expand Up @@ -183,7 +186,9 @@ function JQLiteDealoc(element){
}
}

function JQLiteUnbind(element, type, fn) {
function JQLiteOff(element, type, fn) {
if ( arguments.length > 4 ) throw jqLiteError('off_args', 'jqLite#off() does not support the `selector` parameter');

This comment has been minimized.

Copy link
@ksheedlo

ksheedlo Aug 6, 2013

Contributor

@mzgol I'm curious why you used

if ( arguments.length > 4 )

instead of

if ( arguments.length >= 4 )

With a read through this code, it looks like we should pass at most 3 arguments to JQLiteOff. But I tried changing it today and Karma failed with a stack overflow. Can you explain what's going on here?

This comment has been minimized.

Copy link
@mgol

mgol Aug 7, 2013

Author Member

@ksheedlo not sure, to be honest; it looks like I wanted to write > 3 here. Looking at the on definition, though, it looks like using the isDefined approach would be more consistent.

var events = JQLiteExpandoStore(element, 'events'),
handle = JQLiteExpandoStore(element, 'handle');

Expand Down Expand Up @@ -216,7 +221,7 @@ function JQLiteRemoveData(element, name) {

if (expandoStore.handle) {
expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
JQLiteUnbind(element);
JQLiteOff(element);
}
delete jqCache[expandoId];
element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
Expand Down Expand Up @@ -338,9 +343,9 @@ var JQLitePrototype = JQLite.prototype = {
if (document.readyState === 'complete'){
setTimeout(trigger);
} else {
this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
// we can not use jqLite since we are not done loading and jQuery could be loaded later.
JQLite(window).bind('load', trigger); // fallback to window.onload for others
JQLite(window).on('load', trigger); // fallback to window.onload for others
}
},
toString: function() {
Expand Down Expand Up @@ -609,7 +614,9 @@ forEach({

dealoc: JQLiteDealoc,

bind: function bindFn(element, type, fn){
on: function onFn(element, type, fn, other1){
if ( isDefined(other1) ) throw jqLiteError('on_args', 'jqLite#on() does not support the `selector` or `eventData` parameters');

var events = JQLiteExpandoStore(element, 'events'),
handle = JQLiteExpandoStore(element, 'handle');

Expand Down Expand Up @@ -649,8 +656,8 @@ forEach({
// http://www.quirksmode.org/js/events_mouse.html#link8
var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};

bindFn(element, eventmap[type], function(event) {
var ret, target = this, related = event.relatedTarget;
onFn(element, eventmap[type], function(event) {
var target = this, related = event.relatedTarget;
// For mousenter/leave call the handler if related is outside the target.
// NB: No relatedTarget if the mouse left/entered the browser window
if ( !related || (related !== target && !contains(target, related)) ){
Expand All @@ -668,7 +675,7 @@ forEach({
});
},

unbind: JQLiteUnbind,
off: JQLiteOff,

replaceWith: function(element, replaceNode) {
var index, parent = element.parentNode;
Expand Down Expand Up @@ -790,19 +797,23 @@ forEach({
/**
* chaining functions
*/
JQLite.prototype[name] = function(arg1, arg2) {
JQLite.prototype[name] = function(arg1, arg2, arg3) {
var value;
for(var i=0; i < this.length; i++) {
if (value == undefined) {
value = fn(this[i], arg1, arg2);
value = fn(this[i], arg1, arg2, arg3);
if (value !== undefined) {
// any function which returns a value needs to be wrapped
value = jqLite(value);
}
} else {
JQLiteAddNodes(value, fn(this[i], arg1, arg2));
JQLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
}
}
return value == undefined ? this : value;
};

// bind legacy bind/unbind to on/off
JQLite.prototype.bind = JQLite.prototype.on;
JQLite.prototype.unbind = JQLite.prototype.off;
});
4 changes: 2 additions & 2 deletions src/ng/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ function Browser(window, document, $log, $sniffer) {
// changed by push/replaceState

// html5 history api - popstate event
if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);
if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
// hashchange event
if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);
if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
// polling
else self.addPollFn(fireUrlChange);

Expand Down
2 changes: 1 addition & 1 deletion src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ function $CompileProvider($provide) {
transcludeScope.$$transcluded = true;

return transcludeFn(transcludeScope, cloneFn).
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
on('$destroy', bind(transcludeScope, transcludeScope.$destroy));
};
})(childTranscludeFn || transcludeFn)
);
Expand Down
2 changes: 1 addition & 1 deletion src/ng/directive/a.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var htmlAnchorDirective = valueFn({
}

return function(scope, element) {
element.bind('click', function(event){
element.on('click', function(event){
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
Expand Down
4 changes: 2 additions & 2 deletions src/ng/directive/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ var formDirectiveFactory = function(isNgForm) {

// unregister the preventDefault listener so that we don't not leak memory but in a
// way that will achieve the prevention of the default action.
formElement.bind('$destroy', function() {
formElement.on('$destroy', function() {
$timeout(function() {
removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
}, 0, false);
Expand All @@ -338,7 +338,7 @@ var formDirectiveFactory = function(isNgForm) {
scope[alias] = controller;
}
if (parentFormCtrl) {
formElement.bind('$destroy', function() {
formElement.on('$destroy', function() {
parentFormCtrl.$removeControl(controller);
if (alias) {
scope[alias] = undefined;
Expand Down
Loading

0 comments on commit f1b94b4

Please sign in to comment.