JQuery attr method can set click handler and inner text

Reading the jQueryUI dialog code I discovered, jQuery .attr () has some undocumented behavior:

<button id="btn1">1</button> <button id="btn2">2</button> $(function() { var props = { text: 'Click it!', click: function () { console.log('Clicked btn:', this); } }; $('#btn1').attr(props, true); // Changes #btn1 inner text to 'Click it!' // and adds click handler $('#btn2').attr(props); // Leaves #btn2 inner text as it is and fires // click function on document ready }); 
  • Can you explain to me how this works? Why should I set true as the second argument after the map attribute-value pairs?
  • Can I use this feature in my projects safely?
+8
javascript jquery jquery-ui jquery-ui-dialog
source share
3 answers

I have a little guess because I am not familiar with the jQuery source. jQuery.attr calls jQuery.access , and the comment above the jQuery.access function says:

 // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it a function 

Upon further investigation, the text() function also calls jQuery.access :

  attr: function( name, value ) { return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); }, ......... text: function( value ) { return jQuery.access( this, function( value ) { ...... }, 

You use attr to install text handlers and events for which attr is not required. However, they all seem to use the same function to do the job, so using undocumented parameters just by chance gives you the expected behavior.

I would find it unacceptable to rely on undocumented behavior to accomplish what you are trying to do here, as any subsequent jQuery update could break your code.

+3
source share

Looking at jQuery 1.8.2 code, the true parameter ultimately comes into the pass variable in a line that states:

 exec = pass === undefined && jQuery.isFunction( value ); 

which, if installed, tells jQuery to check the value that belongs to the key, and if it is a function, call it immediately. Therefore, click: function(...) will call this function, not register this function.

It seems that the .method(function() { ... } versions of various jQuery functions work, that is, those where instead of passing a specific value for a property, you pass a function that itself passed the original value and whose return value is assigned to the corresponding property.

Can I use this feature in my projects safely?

I would not want until this is documented.

+2
source share

It is interesting. I can't pretend to tell you / why it works this way, and I think it might even be a reason to present this as a jQuery error report, because the behavior they document does not come out as I expected.

The following quote is displayed on this page below: http://api.jquery.com/attr/

"Note: if nothing is returned in the setter function (that is, the (index, attr) {} function) or undefined is returned, the current value does not change. This is useful for selectively setting values ​​when certain criteria are met.

This made me play a bit on jsFiddle: http://jsfiddle.net/mori57/GvLcE/

Note that, contrary to their documentation, cases 8 and 9 return either zero or nothing. Looking at what Alnimak mentioned, it seems to make sense, since their test / actually / only confirms that he / is a function / not that this function returns (.isFunction should only return true / false, which differs from that that the return value is true / false).

In the end, however, I would agree with Alnitak and bcoughlan that this is not the functionality you should rely on, although I would add that in addition to this, it is unstable, as it may be changed in future versions of jQuery, also bad the practice is to rely on hacks depending on undocumented functions, because future developers of the code you write today (and this includes you in 2-4 months!) could very easily forget what is, or why, to install it this way. It is much better to be explicit and use the functionality as documented so that you understand for yourself and others what your code should do.

0
source share

All Articles