We are able to move JavaScript to the footer on all pages of our site except the Calendar views pages that use calendar_overlap.js: http://cgit.drupalcode.org/calendar/tree/js/calendar_overlap.js?id=1c6e935

This script causes the views to render as broken. As soon as we disable AdvAgg's move JS to the footer, the page works as expected.

What about adding a textarea immediately below "Move JS to the footer" that is "Disable 'move JS to the footer' on specific pages"? This would be similar to the textareas already in place under "Inline CSS/JS on Specific Pages".

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ron_s created an issue. See original summary.

ron_s’s picture

Looking more closely at the code, another idea would be to make the values in $all_in_footer_list (or something similar to it) accessible through a textarea. This would allow developers to enter a path such as "/sites/all/modules/calendar/js/calendar_overlap.js" to not be moved to the footer.

mikeytown2’s picture

This should do it. What it's saying is if the calendar_overlap.js file is included then do not put these files in the footer as well.

/**
 * Implements hook_advagg_mod_get_lists_alter().
 */
function hook_advagg_mod_get_lists_alter(&$lists) {
  if (module_exists('calendar')) {
    $calendar_path = drupal_get_path('module', 'calendar');
    $lists[6][$calendar_path . '/js/calendar_overlap.js'] = array(
      '/jquery.js',
      '/jquery.min.js',
      '/jquery.once.js',
      '/drupal.js',
      'settings',
    );
  }
}
ron_s’s picture

Thanks for the alter code, certainly makes sense to handle it that way. We will give it a try.

Was also asking if it might be worthwhile to provide an option in the user interface for developers. Possibly leverage the "per file settings" code used on the JS compression page, and allow devs to select which JS files will cause core files to not be put in the footer?

mikeytown2’s picture

For how simple it seems making a decent interface for this would take a lot of effort. So in that front I'm open to patches, I will not be the one creating it.

ron_s’s picture

Thank you, I was not suggesting it is a simple task. I was merely offering the 'per file settings' functionality as a representative example, and asking if you felt it would be worthwhile functionality to add. You have a much better sense of what features might be valued by those who use the module than I do.

Thanks for the feedback and we'll give the hook a try shortly.

ron_s’s picture

We have tested the hook in #3 and looks like it does the job. Thank you very much!

Do you think it would it be of value to add the hook to advagg.api.php with an example for others?

ron_s’s picture

On closer examination, I think I spoke too soon. Looks like the cache was not fully cleared when I last checked, and the suggested hook doesn't impact the result. I'm only able to see calendar days if I disable moving JavaScript to the footer.

See attached images.

ron_s’s picture

Was looking at the calendar-day-overlap.tpl.php template, and it has inline jQuery to hide the container while the page is rendering. This seems to be the issue, since #single-day-container is being loaded with content, but has CSS of "visibility:hidden".

What's the proper way to handle inline JS from other modules with AdvAgg?

http://cgit.drupalcode.org/calendar/tree/theme/calendar-day-overlap.tpl....
http://cgit.drupalcode.org/calendar/tree/theme/calendar-day-overlap.tpl....

  <?php if (!empty($scroll_content)): ?>
  <script>
    try {
      // Hide container while it renders...  Degrade w/o javascript support
      jQuery('#single-day-container').css('visibility','hidden');
    }catch(e){ 
      // swallow 
    }
  </script>
  <?php endif; ?>
<?php if (!empty($scroll_content)): ?>
<script>
try {
  // Size and position the viewport inline so there are no delays
  calendar_resizeViewport(jQuery);
  calendar_scrollToFirst(jQuery);
  jQuery('#single-day-container').css('visibility','visible');
}catch(e){ 
  // swallow 
}
</script>
<?php endif; ?>
mikeytown2’s picture

AdvAgg does it's best in terms of handling js that has been added without drupal_add_js(). In regards to js that has been added to a tpl file that's tricky. If the contents of that tpl file are available inside of template_process_html() then advagg_mod should be able to wrap the inline js by enabling the "Put a wrapper around inline JS if it was added in the content section incorrectly" checkbox; you can play around with "Use XPath instead of regex when searching for inline scripts" to see if XPath does a better job in comparison to regex.

ron_s’s picture

Thanks for the suggestions, still got the same results.

Would you recommend the best way to fix this would be by patching Calendar?

mikeytown2’s picture

With that enabled do the script tags get a wrapper in the html output?

ron_s’s picture

It seems as though they do. This is the code at the start of #single-day-container:

<div id="single-day-container">
    <script>
function advagg_mod_1() {
  // Count how many times this function is called.
  advagg_mod_1.count = ++advagg_mod_1.count || 1;
  try {
    if (advagg_mod_1.count <= 40) {
      
    try {
  	  // Hide container while it renders...  Degrade w/o javascript support
      jQuery('#single-day-container').css('visibility','hidden');
    }catch(e){ 
      // swallow 
    }
  

      // Set this to 100 so that this function only runs once.
      advagg_mod_1.count = 100;
    }
  }
  catch(e) {
    if (advagg_mod_1.count >= 40) {
      // Throw the exception if this still fails after running 40 times.
      throw e;
    }
    else {
      // Try again in 250 ms.
      window.setTimeout(advagg_mod_1, 250);
    }
  }
}
function advagg_mod_1_check() {
  if (window.jQuery && window.Drupal && window.Drupal.settings) {
    advagg_mod_1();
  }
  else {
    window.setTimeout(advagg_mod_1_check, 250);
  }
}
advagg_mod_1_check();</script>

And this is the code immediately after the "single-day-footer" at the end of the content section:

<script>
function advagg_mod_2() {
  // Count how many times this function is called.
  advagg_mod_2.count = ++advagg_mod_2.count || 1;
  try {
    if (advagg_mod_2.count <= 40) {
      
try {
  // Size and position the viewport inline so there are no delays
  calendar_resizeViewport(jQuery);
  calendar_scrollToFirst(jQuery);
  jQuery('#single-day-container').css('visibility','visible');
}catch(e){ 
  // swallow 
}


      // Set this to 100 so that this function only runs once.
      advagg_mod_2.count = 100;
    }
  }
  catch(e) {
    if (advagg_mod_2.count >= 40) {
      // Throw the exception if this still fails after running 40 times.
      throw e;
    }
    else {
      // Try again in 250 ms.
      window.setTimeout(advagg_mod_2, 250);
    }
  }
}
function advagg_mod_2_check() {
  if (window.jQuery && window.Drupal && window.Drupal.settings) {
    advagg_mod_2();
  }
  else {
    window.setTimeout(advagg_mod_2_check, 250);
  }
}
advagg_mod_2_check();</script></div>
mikeytown2’s picture

At this point yes it seems like calendar's js code is not defer safe. I've had similar issues with just about every map's js code as well so it's not unheard of.

ron_s’s picture

Are there issues or patches for maps you can point me to so I can create a Calendar module patch? Thanks.

mikeytown2’s picture

Unfortunately no. At this point creating a solution based off of #3 seems like the best option unless you can make the js "async safe", which would take a lot of effort to do most likely. For maps I use a solution similar to #3

NickDickinsonWilde’s picture

Here's an alternate solution...
patch attached that adds a $footer_page_skip_list to advagg_mod_js_move_to_footer().
Also adds a field to the advagg_mod's admin page to add pages to the list.

So @ron_s: if you tell us the path to that calender, assuming @mikeytown2 is okay with the idea/my implementation of it, that could also be added to the patch and then the next version of advagg would "just work" out of the box with that calendar module.

NickDickinsonWilde’s picture

Status: Active » Needs review
ron_s’s picture

Nick, thanks for the patch. I don't have time at the moment to review, but most likely I will next week.

Regarding "just working" out of the box with the Calendar module, it would be the calendar/week and calendar/day paths. However, I'm not sure if it's best to add this by default, or provide some guidance in the module notes.

If the Calendar module owners update the JS in the future, there could be a situation where the paths don't need to be included. Also, if a Drupal developer chooses not to use the default Overlap functionality, we would be skipping AdvAgg's capabilities on a page where it could be enabled. Another potential issue is if a developer changes the path of their calendar views, and doesn't realize AdvAgg has hard-coded calendar paths.

mikeytown2’s picture

I'm hesitant on doing this per page; being able to target the js file that doesn't work seems like a more sustainable option.

  • mikeytown2 committed 57a9e1a on 7.x-2.x
    Issue #2632512 by mikeytown2: Allow disabling of move js to footer if a...

  • mikeytown2 committed 31febda on 7.x-2.x
    Issue #2632512 by mikeytown2: Allow defer and async to be modifed.
    
mikeytown2’s picture

Changed the hook from #3 so it has access to the $js list and it can change the $move_js_to_footer variable. This patch has been committed and with it you should be able to do what you want by using the hook like this

/**
 * Implements hook_advagg_mod_get_lists_alter().
 */
function hook_advagg_mod_get_lists_alter(&$lists, $js) {
  if (module_exists('calendar')) {
    $calendar_path = drupal_get_path('module', 'calendar');
    if (isset($js[$calendar_path . '/js/calendar_overlap.js'])) {
      $lists[7] = 0;
    }
  }
}

Also committed a patch that allows for the async and defer settings to be changed as well.

ron_s’s picture

@mikeytown, thanks for these patches. I finally had a chance to test and was able to get it to work successfully.

I was setting both the $move_js_to_footer and $defer_setting values in the user interface, so I had to add $lists[8] = 0; to the function too. Worked just as I would expect.

Status: Fixed » Closed (fixed)

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