Update boolean check to avoid crashes, add all name fixes to propFix (properties are case-sensitive in all browsers), add tests for prop
This commit is contained in:
parent
a9d9f8c542
commit
97144424cc
2 changed files with 95 additions and 66 deletions
|
@ -337,9 +337,12 @@ jQuery.extend({
|
||||||
return hooks.get( elem, name );
|
return hooks.get( elem, name );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var boolProp = elem[ jQuery.propFix[ name ] || name ];
|
var boolProp;
|
||||||
|
|
||||||
if ( typeof boolProp === "boolean" ) {
|
// Align boolean attributes with corresponding properties
|
||||||
|
// Do not check the property if the name contains characters
|
||||||
|
// valid for attributes, but not for properties
|
||||||
|
if ( !rinvalidChar.test( name ) && typeof (boolProp = elem[ jQuery.propFix[ name ] || name ]) === "boolean" ) {
|
||||||
return boolProp ?
|
return boolProp ?
|
||||||
name.toLowerCase() :
|
name.toLowerCase() :
|
||||||
undefined;
|
undefined;
|
||||||
|
@ -354,7 +357,7 @@ jQuery.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAttr: function( elem, name ) {
|
removeAttr: function( elem, name ) {
|
||||||
if ( elem.nodeType === 1 ) {
|
if ( elem.nodeType === 1 ) {
|
||||||
name = jQuery.attrFix[ name ] || name;
|
name = jQuery.attrFix[ name ] || name;
|
||||||
|
@ -404,7 +407,17 @@ jQuery.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
propFix: {
|
propFix: {
|
||||||
readonly: "readOnly"
|
tabindex: "tabIndex",
|
||||||
|
readonly: "readOnly",
|
||||||
|
"for": "htmlFor",
|
||||||
|
"class": "className",
|
||||||
|
maxlength: "maxLength",
|
||||||
|
cellspacing: "cellSpacing",
|
||||||
|
cellpadding: "cellPadding",
|
||||||
|
rowspan: "rowSpan",
|
||||||
|
colspan: "colSpan",
|
||||||
|
usemap: "useMap",
|
||||||
|
frameborder: "frameBorder"
|
||||||
},
|
},
|
||||||
|
|
||||||
prop: function( elem, name, value ) {
|
prop: function( elem, name, value ) {
|
||||||
|
@ -446,18 +459,9 @@ jQuery.extend({
|
||||||
|
|
||||||
// IE6/7 do not support getting/setting some attributes with get/setAttribute
|
// IE6/7 do not support getting/setting some attributes with get/setAttribute
|
||||||
if ( !jQuery.support.getSetAttribute ) {
|
if ( !jQuery.support.getSetAttribute ) {
|
||||||
jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
|
|
||||||
readonly: "readOnly",
|
// propFix is more comprehensive and contains all fixes
|
||||||
"for": "htmlFor",
|
jQuery.attrFix = jQuery.propFix;
|
||||||
"class": "className",
|
|
||||||
maxlength: "maxLength",
|
|
||||||
cellspacing: "cellSpacing",
|
|
||||||
cellpadding: "cellPadding",
|
|
||||||
rowspan: "rowSpan",
|
|
||||||
colspan: "colSpan",
|
|
||||||
usemap: "useMap",
|
|
||||||
frameborder: "frameBorder"
|
|
||||||
});
|
|
||||||
|
|
||||||
// Use this for any attribute on a form in IE6/7
|
// Use this for any attribute on a form in IE6/7
|
||||||
formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
|
formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
|
||||||
|
|
|
@ -4,16 +4,14 @@ var bareObj = function(value) { return value; };
|
||||||
var functionReturningObj = function(value) { return (function() { return value; }); };
|
var functionReturningObj = function(value) { return (function() { return value; }); };
|
||||||
|
|
||||||
|
|
||||||
test("jQuery.attrFix integrity test", function() {
|
test("jQuery.attrFix/jQuery.propFix integrity test", function() {
|
||||||
expect(1);
|
expect(2);
|
||||||
|
|
||||||
// This must be maintained and equal jQuery.attrFix when appropriate
|
// This must be maintained and equal jQuery.attrFix when appropriate
|
||||||
// Ensure that accidental or erroneous property
|
// Ensure that accidental or erroneous property
|
||||||
// overwrites don't occur
|
// overwrites don't occur
|
||||||
// This is simply for better code coverage and future proofing.
|
// This is simply for better code coverage and future proofing.
|
||||||
var propsShouldBe;
|
var props = {
|
||||||
if ( !jQuery.support.getSetAttribute ) {
|
|
||||||
propsShouldBe = {
|
|
||||||
tabindex: "tabIndex",
|
tabindex: "tabIndex",
|
||||||
readonly: "readOnly",
|
readonly: "readOnly",
|
||||||
"for": "htmlFor",
|
"for": "htmlFor",
|
||||||
|
@ -25,54 +23,19 @@ test("jQuery.attrFix integrity test", function() {
|
||||||
colspan: "colSpan",
|
colspan: "colSpan",
|
||||||
usemap: "useMap",
|
usemap: "useMap",
|
||||||
frameborder: "frameBorder"
|
frameborder: "frameBorder"
|
||||||
};
|
},
|
||||||
|
propsShouldBe;
|
||||||
|
|
||||||
|
if ( !jQuery.support.getSetAttribute ) {
|
||||||
|
propsShouldBe = props;
|
||||||
} else {
|
} else {
|
||||||
propsShouldBe = {
|
propsShouldBe = {
|
||||||
tabindex: "tabIndex"
|
tabindex: "tabIndex"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
same(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check");
|
deepEqual(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check");
|
||||||
});
|
deepEqual(props, jQuery.propFix, "jQuery.propFix passes integrity check");
|
||||||
|
|
||||||
test("prop(String, Object)", function() {
|
|
||||||
expect(19);
|
|
||||||
equals( jQuery("#text1").prop("value"), "Test", "Check for value attribute" );
|
|
||||||
equals( jQuery("#text1").prop("value", "Test2").prop("defaultValue"), "Test", "Check for defaultValue attribute" );
|
|
||||||
equals( jQuery("#select2").prop("selectedIndex"), 3, "Check for selectedIndex attribute" );
|
|
||||||
equals( jQuery("#foo").prop("nodeName").toUpperCase(), "DIV", "Check for nodeName attribute" );
|
|
||||||
equals( jQuery("#foo").prop("tagName").toUpperCase(), "DIV", "Check for tagName attribute" );
|
|
||||||
equals( jQuery("<option/>").prop("selected"), false, "Check selected attribute on disconnected element." );
|
|
||||||
|
|
||||||
var body = document.body, $body = jQuery( body );
|
|
||||||
ok( $body.prop("nextSibling") === null, "Make sure a null expando returns null" );
|
|
||||||
body.foo = "bar";
|
|
||||||
equals( $body.prop("foo"), "bar", "Make sure the expando is preferred over the dom attribute" );
|
|
||||||
body.foo = undefined;
|
|
||||||
ok( $body.prop("foo") === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
|
|
||||||
|
|
||||||
var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option");
|
|
||||||
optgroup.appendChild( option );
|
|
||||||
select.appendChild( optgroup );
|
|
||||||
|
|
||||||
equals( jQuery(option).prop("selected"), true, "Make sure that a single option is selected, even when in an optgroup." );
|
|
||||||
equals( jQuery(document).prop("nodeName"), "#document", "prop works correctly on document nodes (bug #7451)." );
|
|
||||||
|
|
||||||
var attributeNode = document.createAttribute("irrelevant"),
|
|
||||||
commentNode = document.createComment("some comment"),
|
|
||||||
textNode = document.createTextNode("some text"),
|
|
||||||
obj = {};
|
|
||||||
jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) {
|
|
||||||
strictEqual( jQuery(ele).prop("nonexisting"), undefined, "prop works correctly for non existing attributes (bug #7500)." );
|
|
||||||
});
|
|
||||||
|
|
||||||
var obj = {};
|
|
||||||
jQuery.each( [document, obj], function( i, ele ) {
|
|
||||||
var $ele = jQuery( ele );
|
|
||||||
$ele.prop( "nonexisting", "foo" );
|
|
||||||
equal( $ele.prop("nonexisting"), "foo", "prop(name, value) works correctly for non existing attributes (bug #7500)." );
|
|
||||||
});
|
|
||||||
jQuery( document ).removeProp("nonexisting");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("attr(String)", function() {
|
test("attr(String)", function() {
|
||||||
|
@ -180,7 +143,7 @@ test("attr(Hash)", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("attr(String, Object)", function() {
|
test("attr(String, Object)", function() {
|
||||||
expect(55);
|
expect(56);
|
||||||
|
|
||||||
var div = jQuery("div").attr("foo", "bar"),
|
var div = jQuery("div").attr("foo", "bar"),
|
||||||
fail = false;
|
fail = false;
|
||||||
|
@ -194,8 +157,7 @@ test("attr(String, Object)", function() {
|
||||||
|
|
||||||
equals( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" );
|
equals( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" );
|
||||||
|
|
||||||
// Fails on IE since recent changes to .attr()
|
ok( jQuery("#foo").attr({ "width": null }), "Try to set an attribute to nothing" );
|
||||||
// ok( jQuery("#foo").attr({"width": null}), "Try to set an attribute to nothing" );
|
|
||||||
|
|
||||||
jQuery("#name").attr("name", "something");
|
jQuery("#name").attr("name", "something");
|
||||||
equals( jQuery("#name").attr("name"), "something", "Set name attribute" );
|
equals( jQuery("#name").attr("name"), "something", "Set name attribute" );
|
||||||
|
@ -226,6 +188,7 @@ test("attr(String, Object)", function() {
|
||||||
equals( document.getElementById("check2").checked, false, "Set checked attribute" );
|
equals( document.getElementById("check2").checked, false, "Set checked attribute" );
|
||||||
equals( jQuery("#check2").prop("checked"), false, "Set checked attribute" );
|
equals( jQuery("#check2").prop("checked"), false, "Set checked attribute" );
|
||||||
equals( jQuery("#check2").attr("checked"), undefined, "Set checked attribute" );
|
equals( jQuery("#check2").attr("checked"), undefined, "Set checked attribute" );
|
||||||
|
|
||||||
jQuery("#text1").prop("readOnly", true);
|
jQuery("#text1").prop("readOnly", true);
|
||||||
equals( document.getElementById("text1").readOnly, true, "Set readonly attribute" );
|
equals( document.getElementById("text1").readOnly, true, "Set readonly attribute" );
|
||||||
equals( jQuery("#text1").prop("readOnly"), true, "Set readonly attribute" );
|
equals( jQuery("#text1").prop("readOnly"), true, "Set readonly attribute" );
|
||||||
|
@ -450,6 +413,68 @@ test("removeAttr(String)", function() {
|
||||||
equals( jQuery("#fx-test-group").attr("height", "3px").removeAttr("height").css("height"), "1px", "Removing height attribute has no effect on height set with style attribute" );
|
equals( jQuery("#fx-test-group").attr("height", "3px").removeAttr("height").css("height"), "1px", "Removing height attribute has no effect on height set with style attribute" );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("prop(String, Object)", function() {
|
||||||
|
expect(30);
|
||||||
|
|
||||||
|
equals( jQuery("#text1").prop("value"), "Test", "Check for value attribute" );
|
||||||
|
equals( jQuery("#text1").prop("value", "Test2").prop("defaultValue"), "Test", "Check for defaultValue attribute" );
|
||||||
|
equals( jQuery("#select2").prop("selectedIndex"), 3, "Check for selectedIndex attribute" );
|
||||||
|
equals( jQuery("#foo").prop("nodeName").toUpperCase(), "DIV", "Check for nodeName attribute" );
|
||||||
|
equals( jQuery("#foo").prop("tagName").toUpperCase(), "DIV", "Check for tagName attribute" );
|
||||||
|
equals( jQuery("<option/>").prop("selected"), false, "Check selected attribute on disconnected element." );
|
||||||
|
|
||||||
|
equals( jQuery("#listWithTabIndex").prop("tabindex"), 5, "Check retrieving tabindex" );
|
||||||
|
jQuery("#text1").prop("readonly", true);
|
||||||
|
equals( document.getElementById("text1").readOnly, true, "Check setting readOnly property with 'readonly'" );
|
||||||
|
equals( jQuery("#label-for").prop("for"), "action", "Check retrieving htmlFor" );
|
||||||
|
jQuery("#text1").prop("class", "test");
|
||||||
|
equals( document.getElementById("text1").className, "test", "Check setting className with 'class'" );
|
||||||
|
equals( jQuery("#text1").prop("maxlength"), 30, "Check retrieving maxLength" );
|
||||||
|
jQuery("#table").prop("cellspacing", 1);
|
||||||
|
equals( jQuery("#table").prop("cellSpacing"), "1", "Check setting and retrieving cellSpacing" );
|
||||||
|
jQuery("#table").prop("cellpadding", 1);
|
||||||
|
equals( jQuery("#table").prop("cellPadding"), "1", "Check setting and retrieving cellPadding" );
|
||||||
|
jQuery("#table").prop("rowspan", 1);
|
||||||
|
equals( jQuery("#table").prop("rowSpan"), 1, "Check setting and retrieving rowSpan" );
|
||||||
|
jQuery("#table").prop("colspan", 1);
|
||||||
|
equals( jQuery("#table").prop("colSpan"), 1, "Check setting and retrieving colSpan" );
|
||||||
|
jQuery("#table").prop("usemap", 1);
|
||||||
|
equals( jQuery("#table").prop("useMap"), 1, "Check setting and retrieving useMap" );
|
||||||
|
jQuery("#table").prop("frameborder", 1);
|
||||||
|
equals( jQuery("#table").prop("frameBorder"), 1, "Check setting and retrieving frameBorder" );
|
||||||
|
QUnit.reset();
|
||||||
|
|
||||||
|
var body = document.body, $body = jQuery( body );
|
||||||
|
ok( $body.prop("nextSibling") === null, "Make sure a null expando returns null" );
|
||||||
|
body.foo = "bar";
|
||||||
|
equals( $body.prop("foo"), "bar", "Make sure the expando is preferred over the dom attribute" );
|
||||||
|
body.foo = undefined;
|
||||||
|
ok( $body.prop("foo") === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
|
||||||
|
|
||||||
|
var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option");
|
||||||
|
optgroup.appendChild( option );
|
||||||
|
select.appendChild( optgroup );
|
||||||
|
|
||||||
|
equals( jQuery(option).prop("selected"), true, "Make sure that a single option is selected, even when in an optgroup." );
|
||||||
|
equals( jQuery(document).prop("nodeName"), "#document", "prop works correctly on document nodes (bug #7451)." );
|
||||||
|
|
||||||
|
var attributeNode = document.createAttribute("irrelevant"),
|
||||||
|
commentNode = document.createComment("some comment"),
|
||||||
|
textNode = document.createTextNode("some text"),
|
||||||
|
obj = {};
|
||||||
|
jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) {
|
||||||
|
strictEqual( jQuery(ele).prop("nonexisting"), undefined, "prop works correctly for non existing attributes (bug #7500)." );
|
||||||
|
});
|
||||||
|
|
||||||
|
var obj = {};
|
||||||
|
jQuery.each( [document, obj], function( i, ele ) {
|
||||||
|
var $ele = jQuery( ele );
|
||||||
|
$ele.prop( "nonexisting", "foo" );
|
||||||
|
equal( $ele.prop("nonexisting"), "foo", "prop(name, value) works correctly for non existing attributes (bug #7500)." );
|
||||||
|
});
|
||||||
|
jQuery( document ).removeProp("nonexisting");
|
||||||
|
});
|
||||||
|
|
||||||
test("removeProp(String)", function() {
|
test("removeProp(String)", function() {
|
||||||
expect(6);
|
expect(6);
|
||||||
var attributeNode = document.createAttribute("irrelevant"),
|
var attributeNode = document.createAttribute("irrelevant"),
|
||||||
|
|
Loading…
Reference in a new issue