4

I upgraded from jquery 1.3.2 to 1.6.4 and found some things in the existing code were not working -

  1. Disabling something -

    $(selector).attr("disabled","");

  2. Checking if radio button is checked or not -

    if($(selector).attr('checked'))

I checked for backwards-incompatibility of the version releases 1.4, 1.5 and 1.6 and found mention of only the issue #2 but no explicit mention of issue #1 above. So I am afraid that like issue #1, I could find more issues with my existing code. I guess I missed something in the "Case-mapping of data- attributes" section of http://blog.jquery.com/2011/05/03/jquery-16-released/. Could somebody please explain the same.

Sources - Upgrading from jQuery 1.3.2 to jQuery 1.5 (or 1.4)

Update

I am still little confused with appropriately replacing attr with prop. I have read .prop() vs .attr() and a few other questions. Wherever I have read so far, it says in majority of the cases I need to do so. But which are the minority cases then? Can somebody give some code examples or situations? How do I find such cases in my existing code? I have also read https://stackoverflow.com/a/6057122/351903 where it is mentioned that -

The thing you really need to be careful with is just do not mix the usage of these for the same property throughout your application

Do I need to replace attr to prop in case of such lines which are working fine now?

$(selector).attr("id")

Update #2
Suppose in my existing code, I have lines like following (which I guess directly affect the behavior or state of the UI widget), but currently there is no check to see if that element is checked or not -

This is there

$(selector).attr("checked","checked"); //setting

But this is not there

if($(selector).attr("checked")) //checking

Should I still replace attr to prop in the setting code, even though setting is working now?

Update #3
Is there some place from where I can get some kind of a list of attributes which directly affect some property of the UI widget? I am still having confusions deciding for which attributes to replace attr to prop. Does anybody else new to this jquery version feel same or am I only one :D ?

Update #4
It looks like, somewhere in between these two versions (1.3.2 to 1.6.4), jquery made element selection more strict.

Details
In a module, have the following HTML -

<div id="60table">
    <div>
        <input type="CHECKBOX" id="60_1" value="1" name="data[reportsInfo][Campaign][2752]">
        <label for="60_1">23 apr new campaign 1</label>
    </div>
    <div>
        <input type="CHECKBOX" id="60_2" value="1" name="data[reportsInfo][Campaign][2753]">
        <label for="60_2">23 apr new campaign 2</label>
    </div>
    <div>
        <input type="CHECKBOX" id="60_3" value="1" name="data[reportsInfo][Campaign][2707]">
        <label for="60_3">2nd camp added</label>
    </div>
</div>

With jquery 1.3.2, the following returned the actual count of inputs -

$("#60table INPUT[type='checkbox']").length

But, now with jquery 1.6.4, the above returns 0 (note that the position of the inputs is like #60table > div > input and not directly under #60table). I have to do $("#60table").find("INPUT[type='checkbox']").length to get the correct number.

Due to this, the following existing code stopped working after the upgrade, even though I replaced the attr with prop -

$("#60table INPUT[type='checkbox']").attr('checked', $("#60").attr("checked")); //I replaced the attr by prop here

So, I am still getting new issues where old code is no more working after the upgrade.

Putting bounty
Because -

  • Element selector logic no more working - I am not sure whether there could be some more codes which are not working. Taking the example of Update 4, when the position of the input is #60table > div > input, was it not correct to select like $("#60table INPUT[type='checkbox']"). If so, are there some other common mistakes which could be there in my project which might have broken.

  • Better explanation of where all to replace attr with prop - I need a more clear distinction between when to use prop instead of attr, with some more examples. As per Jon's answer -

If it directly affects the behavior or state of the UI widget use prop; otherwise use attr.

Where can I get some kind of a list of attributes which directly affect some property of the UI widget

Community
  • 1
  • 1
Sandeepan Nath
  • 8,771
  • 17
  • 66
  • 131
  • 1
    You should replace `.attr("checked", "checked")` with `.prop("checked", true)`. I 'm not sure what you mean "even though checking is working now". – Jon Apr 17 '12 at 09:15
  • sorry I meant to say even though setting is working now – Sandeepan Nath Apr 17 '12 at 09:19

2 Answers2

9

The issue is not related to the case-mapping of data attributes at all, it's simply due to the evolution of the attribute/property API:

In the past, jQuery has not drawn a clear line between properties and attributes. Generally, DOM attributes represent the state of DOM information as retrieved from the document, such as the value attribute in the markup . DOM properties represent the dynamic state of the document; for example if the user clicks in the input element above and types def the .prop("value") is abcdef but the .attr("value") remains abc.

In most cases, the browser treats the attribute value as the starting value for the property, but Boolean attributes such as checked or disabled have unusual semantics.

As for missing other related breaking changes, it should be enough to search your code for uses of attr and replace with prop appropriately; given how attr tends to be used most of the time, the majority of the calls should typically be replaced.

Update: Let's define appropriately.

The key idea is that elements have HTML attributes: <input name="foo" disabled> has the attributes id and disabled; id has a value, while disabled does not. One of these attributes directly affects a property of the UI widget that the browser renders to represent this element (the input box is disabled, in the sense that a desktop app control is). So the rule of thumb is:

If it directly affects the behavior or state of the UI widget use prop; otherwise use attr.

In the example you mention, the id is an abstract quantity that does not directly affect the behavior or state of any elements; therefore you should continue to use attr for it.

Update 2:

Should I still replace attr to prop in the setting code, even though setting is working now?

Yes, you should because jQuery's documentation says so. And as you mention earlier in the question, mixing prop and attr can lead to problematic behavior.

Update 3:

Is there some place from where I can get some kind of a list of attributes which directly affect some property of the UI widget? I am still having confusions deciding for which attributes to replace attr to prop.

Not really. A rule of thumb which does apply here is that if something is a boolean value then prop is most likely the correct way to access it.

Update 4:

It looks like, somewhere in between these two versions (1.3.2 to 1.6.4), jquery made element selection more strict.

It's actually Sizzle that is responsible for resolving matching elements from selectors (jQuery comes with Sizzle built-in). I don't know what change is responsible for the altered behavior, but the culprit is your id which starts with a number. This is not valid HTML 4.01, but for some reason it makes a difference in Sizzle as well. The workaround is simple: don't start your id with a digit.

The other workaround that you discovered (breaking up the selector in two and using .find) is valid because in the special case where the selector is of the form #id, jQuery directly calls getElementById instead of invoking Sizzle.

Community
  • 1
  • 1
Jon
  • 396,160
  • 71
  • 697
  • 768
  • Thanks for the answer. Please read the **Update** section in my question. – Sandeepan Nath Apr 17 '12 at 08:22
  • @SandeepanNath: Updated the answer, check it out. – Jon Apr 17 '12 at 09:00
  • thanks again. one last question, may be silly question, for now I think. Please check **Update #2**. – Sandeepan Nath Apr 17 '12 at 09:08
  • By the way, is there some place from where I can get some kind of a list of attributes which directly affect some *property of the UI widget*? I am still having confusions deciding for which attributes to replace `attr` to `prop`. Does anybody else new to this jquery version feel same or am I only one :D ? – Sandeepan Nath Apr 17 '12 at 12:55
  • started bounty... please see if you can help further – Sandeepan Nath May 09 '12 at 13:35
  • Sandeep, I think Jon explained it pretty clearly. If the attribute affects behavior, use prop, if not, use attr. As an example, class attributes and id attributes don't affect how the page appears, so use attr. However, checked and disabled both affect how input elements appear on the page, so use prop. Hope that helps. +1 for Jon! – jmort253 May 10 '12 at 02:18
  • Guys please check the *Element selector logic no more working* section under **Putting bounty** at least. This has not yet been answered by anybody. – Sandeepan Nath May 15 '12 at 12:21
  • @SandeepanNath: I updated the answer to cover your updates. Tip: if you want someone to be notified of your comment, start it with `@username`. – Jon May 15 '12 at 17:24
1

To answer your update #4:

An ID attribute should not start with digits

The reason why $('#60table') works is because inside jQuery that's optimized as document.getElementById('#60table') which usually works in browsers, under protest :)

But when you start using a combined expression such as $('#60table input[...]') the Sizzle engine gets run, which uses stricter rules for its query.

Hope that helps.

Ja͢ck
  • 161,074
  • 33
  • 239
  • 294