Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
base repository: angular/angular.js
Choose a Base Repository
angular/angular.js
Anuj16/angular.js
ArslanRafique/angular.js
DeborahK/angular.js
EpokK/angular.js
HaoWu/angular.js
IgorMinar/angular.js
JKLFA/angular.js
KAUG/angular.js
Kaic-zz/angular.js
Metric7/angular.js
MikhailTatsky/angular.js
NAzT/angular.js
Narretz/angular.js
Partoo/angular.js
PeterBoesenberg/angular.js
PoshHsu/angular.js
ScxFiction/angular.js
SeanMBe/angular.js
Sharique-Hasan/angular.js
Shipow/angular.js
SjB/angular.js
Sophrinix/angular.js
SumitMunot/angular.js
TEHEK/angular.js
abhisec/angular.js
abnerlinan/angular.js
abrons/angular.js
acosme/angular.js
adam-singer/angular.js
addyosmani/angular.js
agborkowski/angular.js
ajperrins/angular.js
alexeagle/angular.js
alxross/angular.js
aminerahmouni/angular.js
amirhhz/angular.js
angeliaz/angular.js
angularjs-jp/angular.js
anjo/angular.js
arantius/angular.js
ardnet2/angular.js
arsh-co/angular.js
bartes/angular.js
bghanchi/angular.js
blinkbox/angular.js
blueslue/angular.js
boltz/angular.js
bolu/angular.js
briceburg/angular.js
brikou/angular.js
btford/angular.js
byplayer/angular.js
ca136/angular.js
calvinhuang/angular.js
cburgdorf/angular.js
chenermeng/angular.js
chris4403/angular.js
cleyshan/angular.js
codeinpeace/angular.js
colinfrei/angular.js
congmo/angular.js
crossbreeze/angular.js
csii/angular.js
cssgist/angular.js
danielfacanha/angular.js
danilopesouza/angular.js
dankrz/angular.js
dashersw/angular.js
dbinit/angular.js
dcu/angular.js
dhl/angular.js
dineshkummarc/angular.js
dolfly/angular.js
dydycloud/angular.js
eburley/angular.js
elfgoh/angular.js
esprehn/angular.js
fergaldoyle/angular.js
fingerskier/angular.js
flamilton/angular.js
fran6co/angular.js
freewind/angular.js
gaboom/angular.js
gijs/angular.js
girikudlur/angular.js
groner/angular.js
gruber76/angular.js
gwoo/angular.js
hackreactor/angular.js
hardikdangar/angular.js
hjoest/angular.js
hkdobrev/angular.js
hoatle/angular.js
huangciyin/angular.js
huangweili/angular.js
huncent/angular.js
hwclass/angular.js
iammerrick/angular.js
ifedotov/angular.js
imaizumi8925/angular.js
imiborbas/angular.js
intelline/angular.js
jajberni/angular.js
jc1arke/angular.js
jeanielight/angular.js
jecons/angular.js
jimrenwick/angular.js
jjp/angular.js
johnlindquist/angular.js
joshkurz/angular.js
jromero75/angular.js
jsonxu/angular.js
kevan/angular.js
kevinelong/angular.js
kinglerzou/angular.js
kkurni/angular.js
kliu/angular.js
kotiya/angular.js
kyuff/angular.js
lamperwang/angular.js
leeight/angular.js
lobsang/angular.js
lrlopez/angular.js
lt1946/angular.js
ludicast/angular.js
lzlf007/angular.js
m13z/angular.js
maciejblinkbox/angular.js
mailtruck/angular.js
manuel-woelker/angular.js
mdolk/angular.js
mernen/angular.js
mgechev/angular.js
mhevery/angular.js
msgilligan/angular.js
nateabele/angular.js
nateflink/angular.js
neolf/angular.js
patcito/angular.js
pdswan/angular.js
petebacondarwin/angular.js
petrovalex/angular.js
phillipkregg/angular.js
phoo/angular.js
pmurias/angular.js
premblinkbox/angular.js
quangv/angular.js
rafa2000/angular.js
rafaalves/angular.js
rahu28/angular.js
recht/angular.js
redg1974/angular.js
ricardohbin/angular.js
rtnpro/angular.js
ruimonteiro84/angular.js
rulers/angular.js
rwaldron/angular.js
sahilmalik5/angular.js
sangam12345/angular.js
santosomar/angular.js
scuxiayiqian/angular.js
shuvozula/angular.js
shyblower/angular-ie7.js
sjhernes/angular.js
snicolai/angular.js
steinjak/angular.js
stephanebisson/angular.js
stevenp-git/angular.js
sum4me/angular.js
suneil/angular.js
supercool27/angular.js
superman-wrdh/angular.js
thegerr09/angular.js
thenyel/angular.js
thughes/angular.js
timothyx/angular.js
timthesinner/angular.js
tleruitte/angular.js
tobyreynold/angular.js
tonitt/angular.js
trochette/angular.js
unirgy/angular.js
vibster/angular.js
vincentferniot/angular.js
vingo/angular.js
virtualSharif/angular.js
vkoroslev/angular.js
vojtajina/angular.js
witkai/angular.js
woodie/angular.js
wuxq/angular.js
xiehekun/angular.js
xrchen/angular.js
yanneves/angular.js
ysiadf/angular.js
yyx990803/angular.js
zfleet/angular.js
zhangruimin/angular.js
ziakina/angular.js
Nothing to show
base: 1ea3d889fa3c
head repository: angular/angular.js
Choose a Head Repository
angular/angular.js
Anuj16/angular.js
ArslanRafique/angular.js
DeborahK/angular.js
EpokK/angular.js
HaoWu/angular.js
IgorMinar/angular.js
JKLFA/angular.js
KAUG/angular.js
Kaic-zz/angular.js
Metric7/angular.js
MikhailTatsky/angular.js
NAzT/angular.js
Narretz/angular.js
Partoo/angular.js
PeterBoesenberg/angular.js
PoshHsu/angular.js
ScxFiction/angular.js
SeanMBe/angular.js
Sharique-Hasan/angular.js
Shipow/angular.js
SjB/angular.js
Sophrinix/angular.js
SumitMunot/angular.js
TEHEK/angular.js
abhisec/angular.js
abnerlinan/angular.js
abrons/angular.js
acosme/angular.js
adam-singer/angular.js
addyosmani/angular.js
agborkowski/angular.js
ajperrins/angular.js
alexeagle/angular.js
alxross/angular.js
aminerahmouni/angular.js
amirhhz/angular.js
angeliaz/angular.js
angularjs-jp/angular.js
anjo/angular.js
arantius/angular.js
ardnet2/angular.js
arsh-co/angular.js
bartes/angular.js
bghanchi/angular.js
blinkbox/angular.js
blueslue/angular.js
boltz/angular.js
bolu/angular.js
briceburg/angular.js
brikou/angular.js
btford/angular.js
byplayer/angular.js
ca136/angular.js
calvinhuang/angular.js
cburgdorf/angular.js
chenermeng/angular.js
chris4403/angular.js
cleyshan/angular.js
codeinpeace/angular.js
colinfrei/angular.js
congmo/angular.js
crossbreeze/angular.js
csii/angular.js
cssgist/angular.js
danielfacanha/angular.js
danilopesouza/angular.js
dankrz/angular.js
dashersw/angular.js
dbinit/angular.js
dcu/angular.js
dhl/angular.js
dineshkummarc/angular.js
dolfly/angular.js
dydycloud/angular.js
eburley/angular.js
elfgoh/angular.js
esprehn/angular.js
fergaldoyle/angular.js
fingerskier/angular.js
flamilton/angular.js
fran6co/angular.js
freewind/angular.js
gaboom/angular.js
gijs/angular.js
girikudlur/angular.js
groner/angular.js
gruber76/angular.js
gwoo/angular.js
hackreactor/angular.js
hardikdangar/angular.js
hjoest/angular.js
hkdobrev/angular.js
hoatle/angular.js
huangciyin/angular.js
huangweili/angular.js
huncent/angular.js
hwclass/angular.js
iammerrick/angular.js
ifedotov/angular.js
imaizumi8925/angular.js
imiborbas/angular.js
intelline/angular.js
jajberni/angular.js
jc1arke/angular.js
jeanielight/angular.js
jecons/angular.js
jimrenwick/angular.js
jjp/angular.js
johnlindquist/angular.js
joshkurz/angular.js
jromero75/angular.js
jsonxu/angular.js
kevan/angular.js
kevinelong/angular.js
kinglerzou/angular.js
kkurni/angular.js
kliu/angular.js
kotiya/angular.js
kyuff/angular.js
lamperwang/angular.js
leeight/angular.js
lobsang/angular.js
lrlopez/angular.js
lt1946/angular.js
ludicast/angular.js
lzlf007/angular.js
m13z/angular.js
maciejblinkbox/angular.js
mailtruck/angular.js
manuel-woelker/angular.js
mdolk/angular.js
mernen/angular.js
mgechev/angular.js
mhevery/angular.js
msgilligan/angular.js
nateabele/angular.js
nateflink/angular.js
neolf/angular.js
patcito/angular.js
pdswan/angular.js
petebacondarwin/angular.js
petrovalex/angular.js
phillipkregg/angular.js
phoo/angular.js
pmurias/angular.js
premblinkbox/angular.js
quangv/angular.js
rafa2000/angular.js
rafaalves/angular.js
rahu28/angular.js
recht/angular.js
redg1974/angular.js
ricardohbin/angular.js
rtnpro/angular.js
ruimonteiro84/angular.js
rulers/angular.js
rwaldron/angular.js
sahilmalik5/angular.js
sangam12345/angular.js
santosomar/angular.js
scuxiayiqian/angular.js
shuvozula/angular.js
shyblower/angular-ie7.js
sjhernes/angular.js
snicolai/angular.js
steinjak/angular.js
stephanebisson/angular.js
stevenp-git/angular.js
sum4me/angular.js
suneil/angular.js
supercool27/angular.js
superman-wrdh/angular.js
thegerr09/angular.js
thenyel/angular.js
thughes/angular.js
timothyx/angular.js
timthesinner/angular.js
tleruitte/angular.js
tobyreynold/angular.js
tonitt/angular.js
trochette/angular.js
unirgy/angular.js
vibster/angular.js
vincentferniot/angular.js
vingo/angular.js
virtualSharif/angular.js
vkoroslev/angular.js
vojtajina/angular.js
witkai/angular.js
woodie/angular.js
wuxq/angular.js
xiehekun/angular.js
xrchen/angular.js
yanneves/angular.js
ysiadf/angular.js
yyx990803/angular.js
zfleet/angular.js
zhangruimin/angular.js
ziakina/angular.js
Nothing to show
compare: 4e6c14dcae4a
  • 10 commits
  • 2 files changed
  • 1 commit comment
  • 1 contributor
Commits on Oct 06, 2016
…butes

jQuery supports removing multiple attributes in one go, jqLite doesn't.
This is now documented.
This is done automatically by browsers in cases where it's needed; the
workaround was only needed for IE<9. The new behavior means boolean attributes
will not be reflected on elements where browsers don't reflect them.

This change aligns jqLite with jQuery 3.

Fixes #14126

BREAKING CHANGE: Previously, all boolean attributes were reflected into
properties in a setter and from a property in a getter, even on elements that
don't treat those attributes in a special way. Now Angular doesn't do it
by itself but relies on browsers to know when to reflect the property. Note that
this browser-level conversions differs between browsers; if you need to change
dynamic state of an element you should modify the property, not the attribute.

See https://jquery.com/upgrade-guide/1.9/#attr-versus-prop- for a more detailed
description about a related change in jQuery 1.9.

To migrate the code follow the example below:

Before:

CSS:
input[checked="checked"] { ... }

JS:
elem1.attr('checked', 'checked');
elem2.attr('checked', false);

After:

CSS:
input:checked { ... }

JS:
elem1.prop('checked', true);
elem2.prop('checked', false);
This change aligns jqLite with jQuery.

Also, the extra `2` second parameter to `setAttribute` has been removed;
it was only needed for IE<9 and latest jQuery doesn't pass it either.

Ref #15126

BREAKING CHANGE: Invoking `elem.attr(attributeName, null)` would set the
`attributeName` atribute value to a string `"null"`, now it removes the
attribute instead.

To migrate the code follow the example below:

Before:

elem.attr(attributeName, null);

After:

elem.attr(attributeName, "null");
This change aligns jqLite with jQuery.

Ref #15126

BREAKING CHANGE: Before, using the `attr` method with an empty string as a value
would remove the boolean attribute. Now it sets it to its lowercase name as
was happening for every non-empty string so far. The only two values that remove
the boolean attribute are now null & false, just like in jQuery.

To migrate the code follow the example below:

Before:

elem.attr(booleanAttrName, '');

After:

elem.attr(booleanAttrName, false);

or:

elem.attr(booleanAttrName, null);
The attr method was refactored to be divided into setter & getter parts
and to handle boolean attributes in each one of them separately instead of
dividing into boolean & non-boolean ones and then handling setter & getter
in both of them. This is because handling boolean & non-boolean attributes
has common parts; in particular handling of the `null` value or using
getAttribute to get the value in the getter.
The bind/unbind aliases to on/off were being assinged in every iteration
of the function assigning traversal methods to the prototype. Now it happens
only once.
The on/off aliases have been available since Angular 1.2. bind/unbind have
been deprecated in jQuery 3.0 so we're following suit in jqLite.
jQuery falls back to prop here but this feature is not very well tested
& documented so let's just skip it here.

Closes #15181
Showing with 122 additions and 29 deletions.
  1. +28 −28 src/jqLite.js
  2. +94 −1 test/jqLiteSpec.js
@@ -56,7 +56,7 @@
* - [`after()`](http://api.jquery.com/after/)
* - [`append()`](http://api.jquery.com/append/)
* - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
* - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
* - [`bind()`](http://api.jquery.com/bind/) (_deprecated_ - to be removed in 1.7.0, use [`on()`](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/)
@@ -78,14 +78,14 @@
* - [`prop()`](http://api.jquery.com/prop/)
* - [`ready()`](http://api.jquery.com/ready/)
* - [`remove()`](http://api.jquery.com/remove/)
* - [`removeAttr()`](http://api.jquery.com/removeAttr/)
* - [`removeAttr()`](http://api.jquery.com/removeAttr/) - Does not support multiple attributes
* - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument
* - [`removeData()`](http://api.jquery.com/removeData/)
* - [`replaceWith()`](http://api.jquery.com/replaceWith/)
* - [`text()`](http://api.jquery.com/text/)
* - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument
* - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
* - [`unbind()`](http://api.jquery.com/unbind/) (_deprecated_ - to be removed in 1.7.0, use [`off()`](http://api.jquery.com/off/)) - Does not support namespaces or event object as parameter
* - [`val()`](http://api.jquery.com/val/)
* - [`wrap()`](http://api.jquery.com/wrap/)
*
@@ -638,33 +638,33 @@ forEach({
},

attr: function(element, name, value) {
var ret;
var nodeType = element.nodeType;
if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT ||
!element.getAttribute) {
return;
}

var lowercasedName = lowercase(name);
if (BOOLEAN_ATTR[lowercasedName]) {
if (isDefined(value)) {
if (value) {
element[name] = true;
element.setAttribute(name, lowercasedName);
} else {
element[name] = false;
element.removeAttribute(lowercasedName);
}
var isBooleanAttr = BOOLEAN_ATTR[lowercasedName];

if (isDefined(value)) {
// setter

if (value === null || (value === false && isBooleanAttr)) {
element.removeAttribute(name);
} else {
return (element[name] ||
(element.attributes.getNamedItem(name) || noop).specified)
? lowercasedName
: undefined;
element.setAttribute(name, isBooleanAttr ? lowercasedName : value);
}
} else if (isDefined(value)) {
element.setAttribute(name, value);
} else if (element.getAttribute) {
// the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
// some elements (e.g. Document) don't have get attribute, so return undefined
var ret = element.getAttribute(name, 2);
// normalize non-existing attributes to undefined (as jQuery)
} else {
// getter

ret = element.getAttribute(name);

if (isBooleanAttr && ret !== null) {
ret = lowercasedName;
}
// Normalize non-existing attributes to undefined (as jQuery).
return ret === null ? undefined : ret;
}
},
@@ -1061,12 +1061,12 @@ forEach({
}
return isDefined(value) ? value : this;
};

// bind legacy bind/unbind to on/off
JQLite.prototype.bind = JQLite.prototype.on;
JQLite.prototype.unbind = JQLite.prototype.off;
});

// bind legacy bind/unbind to on/off
JQLite.prototype.bind = JQLite.prototype.on;
JQLite.prototype.unbind = JQLite.prototype.off;


// Provider for private $$jqLite service
/** @this */
@@ -598,7 +598,7 @@ describe('jqLite', function() {


describe('attr', function() {
it('should read write and remove attr', function() {
it('should read, write and remove attr', function() {
var selector = jqLite([a, b]);

expect(selector.attr('prop', 'value')).toEqual(selector);
@@ -635,6 +635,43 @@ describe('jqLite', function() {
expect(select.attr('multiple')).toBe('multiple');
});

it('should not take properties into account when getting respective boolean attributes', function() {
// Use a div and not a select as the latter would itself reflect the multiple attribute
// to a property.
var div = jqLite('<div>');

div[0].multiple = true;
expect(div.attr('multiple')).toBe(undefined);

div.attr('multiple', 'multiple');
div[0].multiple = false;
expect(div.attr('multiple')).toBe('multiple');
});

it('should not set properties when setting respective boolean attributes', function() {
// jQuery 2.x has different behavior; skip the test.
if (isJQuery2x()) return;

// Use a div and not a select as the latter would itself reflect the multiple attribute
// to a property.
var div = jqLite('<div>');

// Check the initial state.
expect(div[0].multiple).toBe(undefined);

div.attr('multiple', 'multiple');
expect(div[0].multiple).toBe(undefined);

div.attr('multiple', '');
expect(div[0].multiple).toBe(undefined);

div.attr('multiple', false);
expect(div[0].multiple).toBe(undefined);

div.attr('multiple', null);
expect(div[0].multiple).toBe(undefined);
});

it('should normalize the case of boolean attributes', function() {
var input = jqLite('<input readonly>');
expect(input.attr('readonly')).toBe('readonly');
@@ -684,6 +721,47 @@ describe('jqLite', function() {
expect(comment.attr('some-attribute','somevalue')).toEqual(comment);
expect(comment.attr('some-attribute')).toBeUndefined();
});

it('should remove the attribute for a null value', function() {
var elm = jqLite('<div attribute="value">a</div>');
elm.attr('attribute', null);
expect(elm[0].hasAttribute('attribute')).toBe(false);
});

it('should not remove the attribute for an empty string as a value', function() {
var elm = jqLite('<div attribute="value">a</div>');
elm.attr('attribute', '');
expect(elm[0].getAttribute('attribute')).toBe('');
});

it('should remove the boolean attribute for a false value', function() {
var elm = jqLite('<select multiple>');
elm.attr('multiple', false);
expect(elm[0].hasAttribute('multiple')).toBe(false);
});

it('should remove the boolean attribute for a null value', function() {
var elm = jqLite('<select multiple>');
elm.attr('multiple', null);
expect(elm[0].hasAttribute('multiple')).toBe(false);
});

it('should not remove the boolean attribute for an empty string as a value', function() {
var elm = jqLite('<select multiple>');
elm.attr('multiple', '');
expect(elm[0].getAttribute('multiple')).toBe('multiple');
});

it('should not fail on elements without the getAttribute method', function() {
forEach([window, document], function(node) {
expect(function() {
var elem = jqLite(node);
elem.attr('foo');
elem.attr('bar', 'baz');
elem.attr('bar');
}).not.toThrow();
});
});
});


@@ -2256,4 +2334,19 @@ describe('jqLite', function() {
expect(onLoadCallback).toHaveBeenCalledOnce();
});
});


describe('bind/unbind', function() {
if (!_jqLiteMode) return;

it('should alias bind() to on()', function() {
var element = jqLite(a);
expect(element.bind).toBe(element.on);
});

it('should alias unbind() to off()', function() {
var element = jqLite(a);
expect(element.unbind).toBe(element.off);
});
});
});

Showing you all comments on commits in this comparison.

@gkalpak

This comment has been minimized.

Copy link
Member

gkalpak commented on 7ceb5f6 Jan 20, 2017

Being a refactor, this BC didn't show up in the changelog/Migration Guide.

You can’t perform that action at this time.