This is easiest to describe by giving you an example.

1. Visit http://www.crca.org.au/Downloads (anonymous user is fine).
2. Type in a Download tag to find (eg "2009 Synod").
3. Click "Apply"

Result is that the correct results are shown where expected in the Downloads section, but in addition, the Ajax congregation locations form in the page footer gets replaced with another copy of the search form and results. (I'd expect just the top one to change, and the congregation links to stay there). A similar thing happens in reverse.

Interestingly, the issue is not seen if you've got filtering already in place. If you do:
1. Visit http://www.crca.org.au/Downloads
2. Select a state in the congregations and click Apply.
3. Type in a tag in the Downloads and click apply.

... then everything works as expected.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

merlinofchaos’s picture

It appears that both views have the same dom ID, which means that the AJAX thinks they are, in fact, the same view. Are you embedding the second view directly in your page.tpl.php using views_embed_view() or something similar? I can't think of too many reasons why this would happen, but if you're embedding it in the page.tpl.php there might be some timing issues causing this.

Nigel Cunningham’s picture

Hi.

It's in a block which is in the footer of every page, not directly in the page.tpl.php.

merlinofchaos’s picture

Is either view cached?

Nigel Cunningham’s picture

I've had to turn off the Ajax on the footer block for now, but will happily turn it back on if you want me to try anything.

Nigel

Nigel Cunningham’s picture

Yes, they're both cached.

Nigel Cunningham’s picture

Disabling caching on the view in the footer seems to make a difference. I disabled caching on the top view first, though, so will just turn that one back on and see if it ruins things again.

Nigel Cunningham’s picture

Just disabling caching for the view in the footer seems to fix it. I re-enabled caching for the sermons view and it continued to work okay.

merlinofchaos’s picture

Status: Active » Fixed

Ok, so the problem is that if the view in the footer is cached when the main view is not on the page, it gets a dom ID of 1, being the only ajax-enabled view on the page. When cached, it will continue to use this id. However, when the other ajax enabled view appears on the page, it also gets a dom ID of 1, and they conflict. You will have to not cache the view in the footer.

Nigel Cunningham’s picture

Okay. Would it be an idea to use unique, constant numbers for cached views so they never conflict, regardless of what else is on the page?

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

sirpy’s picture

Status: Closed (fixed) » Needs work

I think this is still a bug, disabling the cache is not a solution. all the uses of dom-id should also work with cached views.
this could be fixed by replacing the cached html string with a new string. or maybe the authors of views have a better idea for a solution?

Nigel Cunningham’s picture

Status: Needs work » Active

This bit me again today. I'd like to see a better fix than disabling caching, too. Could the dom id somehow be made a function of some unique attribute of the underlying view?

Nigel Cunningham’s picture

Version: 6.x-2.8 » 6.x-2.10
sirpy’s picture

Status: Active » Needs review

what I did to solve the problem for me is generate random ids for the view
in the file theme.inc(views/theme), i've changed the line that issues a dom_id to this:
$vars['dom_id'] = !empty($view->dom_id) ? $view->dom_id : rand(1,10000000)/*$dom_id++*/;
there is a chance of a collision but it's not that probable, 1 in 10M i'd say:)
ofcourse you could use even the miliseconds passed as an id,or even larger numbers.

Nigel Cunningham’s picture

Wouldn't random id's nullify caching?

dawehner’s picture

Status: Needs review » Needs work

sirpy: Please provide a patch, its easier to read patches then text :p

But i think this could work fine. In drupal7 there is a helper function for this, see http://api.drupal.org/api/function/drupal_html_id/7

gnindl’s picture

Version: 6.x-2.10 » 6.x-2.11
Status: Needs work » Needs review
FileSize
154.37 KB
1.41 KB

I ran across the same problem, as I was invoking the views_embed_view() several times on the same form (original bug: #829886: NodeReference Explorer produces ineffective radio-buttons after a filter is applied).

Ajax Views are generating the classes "view-dom-id-[counter]", e. g. view-dom-id-1, view-dom-id-2, for identifying, updating, filtering and sorting view items. It raises a problem as with each call of views_embed_view() in a different request, the counter is reset. It results in embedded views having the same identifier which means that other views are unintentionally updated (see screen shot).

I propose using the display ids instead of incremental integers, as they guarantee an unique identifier (see patch).

merlinofchaos’s picture

It's not unique if you're using the same display multiple times, though. That is the problem.

I suspect maybe we need to be smarter about the counter and increment it per display per view, perhaps.

gnindl’s picture

Ok you are right.

This next patch generates a dom id in combination of view name, display id and an incremental counter (static variable).

So, let's imagine the following three cases which process requests on the same HTML page:
1. Render the SAME view displays within a SINGLE request: should be fine as dom ids like "view-dom-id-VIEWNAME-DISPLAYID1-1", "view-dom-id-VIEWNAME-DISPLAYID1-2", "view-dom-id-VIEWNAME-DISPLAYID2-1", "view-dom-id-VIEWNAME-DISPLAYID2-2"
2. Render DIFFERENT displays with DIFFERENT requests: should be fine as dom ids like "view-dom-id-VIEWNAME-DISPLAYID1-1", "view-dom-id-VIEWNAME-DISPLAYID2-1". This isn't true with the current approach where you have just an incremental counter. Relating to the previous example the dom ids of both views would be like "view-dom-id-1"
3. Render the SAME view displays within DIFFERENT requests: you still have id clashes

For 3. I provided the workaround in the patch where client can set the dom id manually, i. e. $_REQUEST['view_dom_id']. Although this might be already captured in the views_ajax() function, clients may bypass this callback by providing custom menu callbacks and embed a view programmatically, i. e. views_embed_view().

walker2238’s picture

I tested #19 in the environment of using a modal. So basically a page view which has a link that pop ups in modal window and it seems to disable that ajax functionality.

My issue which I created before knowing about this issue: http://drupal.org/node/876384

ezar’s picture

+1
Please commit to actual version!
Thanks!

hefox’s picture

works for me so far; will have more feedback later to see if problem returns.

(Didn't test the patch word for word, used hook theme register alter to add a preprocess before template_preprocess_views_views to set the dom id before views does so don't have to remember to upgrade if this doesn't get in soon.)

jonhy81’s picture

+ 1.
Nice job gnindl. thanks

JaceRider’s picture

+ 1.

Needed this as I was loading a view via ajax on top of a page with an already existing view. This resolved the issue of both being updated when the latter was filtered via ajax.

merlinofchaos’s picture

Status: Needs review » Needs work

Overall this approach seems good.

+  //If dom_id property is already set, use it as identifier
..
+  //It allows clients to set the dom_id per request as they may bypass the views_ajax() function
+  //with a custom menu call back and the invokation of views_embed_view(). It is needed when
+  //the same display is rendered mulitple times on a common HTML page by separate requests. 
+  //Clients are supposed to look up the view_dom_id entry the Drupal.settings.views.AjaxViews
+  //array and calculate a unique id by themselves.

Should be spaces between the // and the text. Sentences should end with periods.

+    do {
+      //dom id, e. g. view-display-1
+      $unique_dom_id = form_clean_id($view->name . '-' . $view->current_display . '-' . ++$counter);
+      //check if dom ids already exists, otherwise increment counter with next loop iteration
+      if (!in_array($unique_dom_id, $dom_ids)) { 
+      	$dom_ids[] = $unique_dom_id;
+      	return $unique_dom_id;
+      }
+    } while ($counter <= count($dom_ids));

Does this have to be a do ... while loop? I tend to avoid them when possible. I realize there are occasions you want them, though.

Also, indentation on the internal if() is wrong, making the } seem really out of place.

-    $dom_id = isset($_REQUEST['view_dom_id']) ? intval($_REQUEST['view_dom_id']) : NULL;
+    $dom_id = isset($_REQUEST['view_dom_id']) ? $_REQUEST['view_dom_id'] : NULL;

Removing the intval() means we need to perform an XSS check on $dom_id because I believe this dom_id will carry back through the view and possibly be output again, opening the door for XSS attacks.

gnindl’s picture

Status: Needs work » Needs review
FileSize
3.72 KB

Included the changes proposed in #25 and generated a new patch (you don't need to apply patch from #19):

- XSS is prevented by using check_plain() function
- Formatting of indents and comments are corrected

Do-While loop:

I couldn't find a more elegant way than using a do-while construct although I try to avoid do-while as it is a bit old fashioned. Putting the same code in a while or for loop requires extra lines of code (correct me if I am wrong). The most elegant way would be to search the dom_ids array by regular expressions and use and incremental counter (I don't see an easy way to do that).

merlinofchaos’s picture

FileSize
4.21 KB

I updated the comments and removed the do ... while loop and simplified the code. I eliminated form_clean_id which I'm afraid of, sine it's already doing it's own uniqueness testing, we shouldn't do that twice. views_css_safe is better in this case.

I did not test this, it definitely could use some testing.

attiks’s picture

I ran into the same problem with 6.x-3.x-dev, patch in #27 works.

In my case I only had 1 ajax enabled view on the page, but both dom's were equal.

FYI:
- First view as exposed as block
- Second view exposed as block and with exposed filters
- Blocks managed by using context
- Views data generated using display suite

inolen’s picture

I was having a problem loading a page with a view in it via ajax, as the new view had the same dom id as a view on my current page (although they were a completely different view).

After changing the view_css_safe func to drupal_clean_css_identifier I manually applied the patch from #27 to my Drupal 7.x-3.x-dev version of Views and was up and going. Thanks!

simon_s’s picture

Also having same problem with views 7.x-3.0-beta3 (described in: http://drupal.org/node/1113512)
Could you please submit the "safe-dom-id-patch" (#27) to the 7.x Version?

attiks’s picture

Version: 6.x-2.11 » 6.x-3.x-dev

patch in #27 worked for me for d6, i think we need some testing for d7 unless someone did test this already? If so please mark this RTBC

crea’s picture

Subscribing

dawehner’s picture

Status: Needs review » Needs work

The patch works for many people
sadly it does not work for 7.x-3.x

+++ theme/theme.inc	20 Jan 2011 21:48:00 -0000
@@ -36,6 +36,51 @@ function _views_theme_functions($hook, $
+    return $view->dom_id;

It would be great if $view->dom_id would be documented in the object.

Powered by Dreditor.

dawehner’s picture

FileSize
1.7 KB
1.7 KB

I tryed to reproduce this issue on 6.x-2.x-dev but wasn't able to do so.

I used two different views for this and embedding both on the same node

wojtha’s picture

#27 works for me on some older 2.x dev (latest fixed issue in changelog is http://drupal.org/node/1096366) so I suppose it is 2 months old. thx!

geoffreyr’s picture

I've been having this issue myself, and I've put together a tiny patch for ajax_view.js that might help, at least from a front end perspective.

Right now, the form processor in Drupal.behaviors.ViewsAjaxView selects the form by ID, but unfortunately if you've got multiple instances of the same view display on the same page, all the exposed forms come out having the same ID. (This behaviour will need to be changed elsewhere, but not now.) This is why you get situations like exposed forms for other views instances only controlling the first one.

My patch mitigates this by using the view variable that gets created when there's a dom_id for that instance of the view. I've added a new variable, view_ctx, which is used to give context to the query that picks up the exposed form.
It starts out as '.view', which should just result in it picking up exposed forms in any view wrapper.
When there's a dom_id found, view_ctx is set to the same as view - a direct reference to the wrapper surrounding that instance of the view. This way, it's able to pick up that unique copy of the exposed form.

I'll still need to check if this works with exposed forms in blocks, or whether it's compatible with Core 7.x and Views 2.x etc.

rashad612’s picture

Will the same solution work for 7.x-3.x-dev ?

Majdi’s picture

#36 don't work for me

bluesband’s picture

i have a same problem with 7.4 , subscribing.

carn1x’s picture

I'm getting this issue in Views 2.11, however the views are entirely unrelated, specific behavior:

* View1: Block: No Ajax, Caching On
* View2: Block: No Ajax, Caching On
* View3: Block: No Ajax, Caching On
* View4: Block: No Ajax, Caching On
* View5: Block: Ajax, Exposed Filters, Caching Off

Submitting the exposed filters for View5, causes Blocks 1, 3, 5 to be rebuilt using the results of View5.

If I remove Caching from View1, which is actually a block with attachment, then the entire problem appears to go away, and ceases to affect View3 as well, even thought View3 may retain it's caching.

inolen’s picture

*bump*

Updated a client to the latest views and forgot all about having applied this patch. Manually applied patch #27 to latest and my problems were yet again solved.

vgulla’s picture

subscribe

carn1x’s picture

I also seem to get different behavior when I'm logged in as admintrator (which isn't recieving this error on an offending page) compared to anonymous / non-admin user which still get this error.

vgulla’s picture

Sorry for posting on multiple issues. I was not sure which one was active and which one will be responded to. This patch http://drupal.org/files/issues/981870-safe-dom-id.patch worked for me too.

Thanks again

carn1x’s picture

Finally took the plunge and manually applied #27, works for me, thanks :)

jamsilver’s picture

Status: Needs work » Needs review
FileSize
2.45 KB

I've rerolled the patch in #27 against views-7.x. With the following changes:

+++ includes/ajax.inc	20 Jan 2011 21:47:59 -0000
@@ -19,7 +19,7 @@ function views_ajax() {
-    $dom_id = isset($_REQUEST['view_dom_id']) ? intval($_REQUEST['view_dom_id']) : NULL;
+    $dom_id = isset($_REQUEST['view_dom_id']) ? check_plain($_REQUEST['view_dom_id']) : NULL;

Ignored this change since the newest version of views seems to sanitize this using preg_replace.

+++ theme/theme.inc	20 Jan 2011 21:48:00 -0000
@@ -36,6 +36,51 @@ function _views_theme_functions($hook, $
+    // Use check_plain() to prevent XSS attacks and encode HTML special characters.
+    return check_plain($_REQUEST['view_dom_id']);

Changed this to mirror the preg_replace line that views-7.x has for sanitizing $_REQUEST['view_dom_id']

Powered by Dreditor.

gnindl’s picture

+1 for patch in comment #27. Thank you!

serialjaywalker’s picture

It seems like this issue should be fixed by the fix in #528606: Content leakage to other blocks when Ajax is enabled.

codesidekick’s picture

If anybody is stuck using an older version of Views (folks using Commons or people on legacy sites) here's a work-around that creates unique dom ids without hacks that assumes you won't add the same display twice on a page which I think is a fair assumption for most users.

In a custom module use :

/**
 * Implements hook_views_pre_render().
 */
function MY_MODULE_views_pre_render(&$view) {
  // Create an AJAX dom ID based on the view name and display to prevent
  // errors that occur when caching views.
  $view->dom_id = $view->name . '-' . $view->current_display;
}

For those playing at home, this method creates a views dom ID using the view name and the display name. If you wanted to be extra special you could combine it with the random number technique http://drupal.org/node/655002#comment-2992098 but I don't think it's necessary for most users.

Status: Needs review » Needs work

The last submitted patch, views_655002_46.patch, failed testing.

yan’s picture

I'm having the same problem with Drupal 6 and Views 2. The workaround from #50 seems to work.

Chris Matthews’s picture

Issue summary: View changes
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