I am using views for a site which requires Prototype as well (I'm using the jquery_compability_module, which seems to be working). Prototype (as well as potentially other js libraries) extends the Array object with additional methods / properties. The views js uses the following form to iterate though what are known to be arrays:

for (i in my_array)

for example (in js/dependent.js):

for (i in Drupal.Views.dependent.activeTriggers) {
   jQuery(Drupal.Views.dependent.activeTriggers[i]).unbind('change');
}

where Drupal.Views.dependent.activeTriggers is known to be an array. When the array is empty, but overloaded with additional properties due to Prototype, this code will iterate through the Array object's properties (i.e. function names), which causes javascript errors.

I fixed this by moving this form to the more traditional:

for (var i = 0; i < Drupal.Views.dependent.activeTriggers.length; i++)

for all instances where it was an array that was being iterated over.

Here is some more info on the larger issue:

http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays/...

Patch file is attached to ticket.

Comments

dawehner’s picture

Why not use $.each(). As far as i know its a quite fast version of foreach.
Additional it will not break with Prototype.

athoune’s picture

it's not a bug with Prototype framework, it's a bug for every one wich add stuff in Array.prototype . The "for a in something" iter over object's attributes, not only array keys.

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new3.74 KB

This code does not ease $.each

merlinofchaos’s picture

Assigned: Unassigned » dawehner

Unfortunately this patch does not apply now. I think at least one of the loops has been changed for this very reason, even though nobody understood why the change. Now that I understand what's going on, I agree with this change.

Can I get a reroll?

dawehner’s picture

Assigned: dawehner » Unassigned
StatusFileSize
new3.75 KB

rerolled the patch

merlinofchaos’s picture

Version: 6.x-2.6 » 7.x-3.x-dev
Assigned: Unassigned » dawehner
Status: Needs review » Patch (to be ported)

Unsurprisingly does not apply to D7. Committed to D6.

merlinofchaos’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev
Status: Patch (to be ported) » Needs work

Reverted this patch.

Not all of the for () loops replaced were for arrays, some were for objects and this syntax broke them.

eugenmayer’s picture

i would actually set this one on wontfix.

https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special_...

In is used in the correct context here and also operates through _objects_ and not only arrays. This "fix" can probably brake a lot other things ( beside the typo in the last for statement...forgetting the .lenght ).

in is used like in the specifications and if prototype does brake it, its not the fault of views. In any case, use $.each can help here a lot

dawehner’s picture

@eugenmayer

Does $.each also works with objects?

eugenmayer’s picture

yes Daniel, it does.

pascalduez’s picture

StatusFileSize
new392 bytes

Hi,

While this issue if more globally related to all "for in" loops I also noticed some missing "var" keywords, resulting in the variable being declared as global. This should really be avoided, especially with variable names like "i".
http://bonsaiden.github.com/JavaScript-Garden/#function.scopes
Patch attached for the base.js file.

As for this issue, there's not much to do to prevent "for in" to iterate over the object / array prototype except the use of object.hasOwnProperty().
Or use jQuery.each()

damien tournoud’s picture

Last time I checked, jQuery.each() iterated over all the properties, not only the own properties.

pascalduez’s picture

StatusFileSize
new3.51 KB

This patch does not fix the prototype issue, just make sure "var" is used in the loops. I thought this would not deserve a separate issue ?
I corrected only one loop in the previous patch, but noticed the same problem at several other places.
Re-worked it.

Edit:

@Damien Confirmed, jQuery.each() does loop over all properties, including the inherited ones:
http://bugs.jquery.com/ticket/6132

damien tournoud’s picture

Correction to #12: if the object enumerated by jQuery.each() is an array-ish, it is enumerated numerically, as an array. The way I see it, that makes this function potentially dangerous to use: it does what a non Javascript programmer would expect it to do on array-ish structures, but not on objects.

pascalduez’s picture

I've been trying to secure each "for in" loops with conditional hasOwnProperty().
But there's also some jQuery.each() used, i.e. in the "ajax_views.js". So all in one it's actually adding quite some code...

This issue is more of the decision making type, as extending Object.prototype is considered a bad practice. Moreover, even with views js patched, good chances are it will break on other parts / scripts, including core ones.

In jQuery they made the choice not to support it.

sk33lz’s picture

Issue summary: View changes
StatusFileSize
new1.5 KB

Re-rolled patch in #13 for latest dev release.

chris matthews’s picture

Status: Needs work » Closed (outdated)

The Drupal 6 branch is no longer supported, please check with the D6LTS project if you need further support. For more information as to why this issue was closed, please see issue #3030347: Plan to clean process issue queue