Updated: Comment #6

Problem/Motivation

Currently the Juicebox javascript (both the library and the gallery-specific js logic) are added with drupal_add_js() and library_load(). This means that whenever a field/view that contains a gallery is built, the js will be included on the page no matter what. This is an issue because sometimes build logic will get triggered even when the embed code does not ultimately get displayed on the page. When this happens javascript is triggered that looks for an embed div that it can't find, and Juicebox errors result.

A specific example is when an entity that contains a gallery comes back as a "hit" in the core Drupal search. In this case the the entity is both built and rendered, even though only a very small snippet will be included on the search results. This leads to the very intrusive "Cannot find div with id on Search page" library error that takes over the whole page.

Proposed resolution

There are a couple layers that need to be addressed. First, this module should start using the '#attached' part of a render array to include all it's js and css assets. This will ensure that its js is only loaded when a gallery is actually rendered. Hopefully this will address most issues.

Secondly, there are potentially special cases where a gallery is rendered by not displayed in full (such as in search results). This will probably require some custom logic that detects incompatible cases/view-modes where a gallery should never be displayed with its assets.

User interface changes

None.

API changes

Sorting all this out may lead to at least one new method on the JuiceboxGalleryInterface, most likely called getEmbed(). This will be used instead of the previous renderEmbed() and will return a render array instead of direct embed markup. The change can be handled internally as part of the fix for this issue, but anyone building galleries programmatically may need to adjust as well (I'm not aware of anyone doing this, but it's worth noting).

Original report by pdesai

Juicebox Error: Cannot find div with id on Search page

I am not sure why juicebox is being added since I don't have the image field in the teaser. Anyway to disable it?

Comments

rjacobs’s picture

Hi pdesai,

Are you saying that you get the Juicebox javascript "Cannot find div with id" error (the one that insists on taking up the whole page) whenever you run a search that finds a match/hit on a node that happens to contain a Juicebox gallery field? Is the behavior that you encounter even if search does not actually render that Juicebox field in the results list?

I just want to better understand what's involved in replicating this.

pdesai’s picture

Yes that is exactly correct. It takes up the whole page, but I don't have a field in the easier.

rjacobs’s picture

Version: 7.x-2.0-beta5 » 7.x-2.x-dev

I see. I was able to replicate this and I think I have an idea about what's going on. It seems that once Drupal finds "hits" for a search phrase (against the search index) it does a full load of the matched nodes, which also builds all the fields on those matched nodes. I assume it does this so that it can extract a teaser of the matched text in context with the rest of node's content for display in the results list.

Anyway, this module currently includes its javascript and css via calls to libraries_load() and drupal_add_js(), which fire when the field is loaded and built. This means that the Juicebox javascript for a field can get included even if the field is never actually rendered. In these cases the embed code does not appear on the page, but javascript is still triggered that expects to find it, hence the error.

The better way to do things will be to add the needed javascript and css via the '#attached' part of a render array, so that it's only added if the field is actually fully rendered and displayed. This is already how things work in the Drupal 8 branch of this module, and I've been meaning to backport the idea to the Drupal 7 version in the interest of "best practices". I hadn't gotten around to that yet as there was no known issue with the old method... until now that is.

This should be a fairly straightforward issue to address, but it will require some refactoring.

pdesai’s picture

Glad you were able to reproduce it. Appreciate the thorough explanation. Looking forward to a patch.

rjacobs’s picture

Well, like so many things, this is actually more complicated than I thought.

There will be great value in switching to '#attached' instead of drupal_add_js() for the gallery javascript additions, but unfortunately it won't solve this specific problem. From what I can see, when a search "hit" is found not only is the found node built, but it's also fully rendered. I guess that the core search method needs to render all of the node text before it can calculate which specific text to display. Because of this it does not matter how the js is included. With either '#attached' or drupal_add_js(), the gallery javascript will still get added. That makes me sad.

Anyway, there is an easy way around this, and it has nothing to do with Juicebox. The key is the fact that Drupal allows you to specify a different view mode for search results, and the gallery field can simply be excluded from that view mode. To do this:

  1. Go to the "manage display" tab for your content type
  2. Expand the custom display settings toward the bottom and click on the "search result" option. This will allow the search result display to use a custom, configurable, view mode.
  3. Save. After the save you'll see a new sub-tab at the top that says "search results" (next to the others like "default" and "teaser"), click on this.
  4. Now, within the search results view more settings, just choose something other than "Juicebox Gallery" for the "format" setting of your gallery field.

After doing this, that search problem should go away, as the Juicebox formatter will no longer be used when any search results are displayed.

This should be a workable fix for most situations, but I'll still give this some thought to see if there is something else the module can do to avoid this.

I also still plan in making that switch to using '#attached' in the code. As I noted, there is still much value in doing that.

rjacobs’s picture

Title: Juicebox Error: Cannot find div with id on Search page » Prevent javascript from being added in contexts were embed code may not be displayed (e.g. "Cannot find div with id" error on search results)
Issue summary: View changes

Add summary as this issue has a few layers, and it'll be easiest to just address them all at once.

  • Commit 532f055 on 7.x-2.x by rjacobs:
    Issue #2217791 by rjacobs: Use #attached for assets and other related...
rjacobs’s picture

The commit above is broad-sweeping and addresses:

  • Usage of '#attached' for assets and refactoring to ensure embed build methods return proper render arrays.
  • Proper detection of view modes for field formatter while building embed code (this has been a long-standing annoyance that I wanted to address but never had motivation for until now).
  • Other various misc cleanup for DX.

This should not only prevent lots of weird cases where that "Cannot find div with id" error could popup, but also lays the foundation to address other specific cases (such as the issue with search results).

rjacobs’s picture

Status: Active » Needs review
StatusFileSize
new5.11 KB

As noted, with the commit above in place the specific search results part can now be addressed. The attached patch simply detects the "search_result" view mode and omits the javascript in that case.

@pdesai, can you test this out against the most recent dev? Note that it will only apply against today's dev or later. For testing you'll want to make sure that you did not follow my suggestion in comment #5. That suggestion is still totally valid and will eliminate this problem (so feel free to use it later), but the point of this patch is to make sure people don't have to do that to avoid the search-related error.

  • Commit f882fbe on 7.x-2.x by rjacobs:
    Issue #2217791 by rjacobs: Part 2 - add filter for search results...
rjacobs’s picture

Version: 7.x-2.x-dev » 8.x-2.x-dev
Status: Needs review » Active

This has decent test coverage in 7.x-2.x, so I committed the final part.

Now there are a couple pieces related to this that will need attention in 8.x-2.x. That D8 branch already processes all js/css via '#attached' keys in a render array, but there may be some value in porting the search results display mode filter logic, etc. I guess I'll just address that in this issue as well...

  • rjacobs committed 30b795c on 8.x-2.x
    Issue #2217791 and Issue #2275051 by rjacobs: Port multiple fixes from 7...
rjacobs’s picture

Status: Active » Fixed

Ok, the relevant pieces have now been ported to 8.x-2.x.

Status: Fixed » Closed (fixed)

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

pdesai’s picture

Great stuff rjacobs!

MO-2’s picture

Version: 8.x-2.x-dev » 7.x-2.x-dev
Status: Closed (fixed) » Active

Hi Guys,

I have a very similar issue that has popped up, but the dev version with the patch doesn't address it. I'm using display suite search and want to use the "search snippet" field to display some of the search text. However, that field must be calling the juicebox JS because I get the following error and the entire search results page is greyed out:

Juicebox Error: Cannot find div with id: "field--node--303--field-article-image--search-index"

Any ideas on a patch for the search snippets?

Thanks ahead of time,

MO

rjacobs’s picture

Hi MO. I suspect that you have indeed found a case that's technically related to the initial issue, but I'm only superficially familiar with Display Suite, so I can't say anything too definitive just yet.

One of the changes that was implemented above is some ad hoc detection of the view mode that Drupal typically uses for rendering entities within the presentation of individual search results. This detection then allows the module to ensure no Juicebox javascript is added when that mode is used (thus preventing the "cannot find div" error in search results lists). This detection is really just a convenience though as it's still also possible to manually set the field instance specifics for the "search result" view mode to not use Juicebox altogether - see comment #5. I might guess that this same thing is also possible for whatever custom view mode Display Suite uses for it's search results. Would you be able to test the numbered steps from comment #5 to see if it applies for display suites as well? You would just have to see if there is a Display Suite equivalent for the "search result" view mode that those steps reference (perhaps it's called something like "Display Suite Search Result").

Either way, I would not be opposed to enhancing the search result detection of the module itself to be aware of Display Suite Search (so manual steps are not needed), but that would requite a bit more analysis.

MO-2’s picture

StatusFileSize
new70.66 KB

Hi RJacobs,

Thanks for the quick response. I have done exactly this. The specific field that is breaking the search results page is the "search snippet" as shown in the attached screenshot. This display field is made available via the display suite search module. When I remove this filed, then the search results page renders correctly. As you can see, I'm only showing the image using the classic formatter (leveraging another module to show only one result). The search snippet field must be referencing the juicebox gallery, but I'm not sure how to troubleshoot this and avoid it from crashing the search results page.

I would like to use the search snippet field because it provides a nice UX on the search results page.

Thanks ahead of time for any ideas,

MO

rjacobs’s picture

Humm, that's interesting. I thought the built-in "Search Result" view mode is what Drupal uses to calculate the search snippet, and not what's actually shown in the search result (i.e., it represents what's rendered before the snippet is calculated). What you've shown seems to indicate that display suite might somehow override this core behavior while also offering it's own separate "snippet" field.

So the big question is how Display Suite sources the data for that "search snippet" field. Can that be configured? Is it possible to tell Display Suite to use a specific view mode when calculating that snippet, or does it always use the full/default view mode to source that data?

Obviously I'm not to clued up on Display Suite :) ... at some point soon I'll have to dig into it on a dev instance.

If this gets too detailed, we will probably want to open a new issue. Things are technically aligned with the comments above, but we may be venturing into "feature request" land if an explicit Display Suite compatibility commit is needed.

rjacobs’s picture

Ok, I think I see what's happening. It looks like Display Suite uses a different view mode for its search snippet, which is not getting detected by Juicebox.

Addressing this will probably require a patch, so opening another issue makes sense. I've opened the follow-up feature request: #2376401: Prevent javascript from being added within a Display Suite search snippet view mode

MO, if you can check-in on that other issue that would be great.

rjacobs’s picture

Status: Active » Closed (fixed)

As a separate follow-up issue is open for the Display Suite case, I'll restore the closed status on this one.