Commit 97144424 authored by timmywil's avatar timmywil

Update boolean check to avoid crashes, add all name fixes to propFix...

Update boolean check to avoid crashes, add all name fixes to propFix (properties are case-sensitive in all browsers), add tests for prop
parent a9d9f8c5
...@@ -337,9 +337,12 @@ jQuery.extend({ ...@@ -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({ ...@@ -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({ ...@@ -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({ ...@@ -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; }; ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment