Problem/Motivation

Aurora modules maintainers thing they should change how core works.

Theme breaks modules:

  • Google Analytics (~400.000 installs)
  • Piwik (~13.000 installs)

Proposed resolution

Remove 'force header' and respect 'header' set by modules.

Remaining tasks

Remove 'force header' and stop moving 'header' scoped JS to footer

User interface changes

None

API changes

Remove design flaws.

Original report by @username

When using the Aurora theme or Omega 4.x or the Magic module and moving scripts to the footer, the code that reports the number of search results ends up after the _paq.push(["trackSiteSearch", "keyword", false, (window.piwik_search_results) ? window.piwik_search_results : 0]); and so because window.piwik_search_results is not set yet, a zero is sent to Piwik and every search ends up in the "Search Keywords with No Results" report.

This small patch just adds the 'force header' option to move the setting of window.piwik_search_results up. See some similar issues in other modules:

#1808966: Add support for Force Header JS Option
#1911380: Add support for Force Header JS Option
#2263211: Keep js in header

CommentFileSizeAuthor
#1 piwik-2309079-1.patch613 bytesstar-szr

Comments

star-szr’s picture

Status: Active » Needs review
StatusFileSize
new613 bytes
hass’s picture

Status: Needs review » Needs work

Force header is not available in the core api.

star-szr’s picture

You're right but adding this doesn't hurt anything, core will ignore that key in the array. It's a contrib API addition agreed upon by multiple developers across projects.

From one of the related issues:

Simply add this to your drupal_add_js call and it will stay put in the header across all modules and themes that support it, and be totally ignored by those that don't.

hass’s picture

Status: Needs work » Closed (works as designed)

scope' => 'header' is a clear statement. If you break modules by ignoring what developers intended you need to fix the broken themes to respect the intended scope.

star-szr’s picture

Status: Closed (works as designed) » Needs review

I don't want to keep switching the status back and forth but…

The problem with that idea is 'header' is the default for drupal_add_js(). So when you are in hook_js_alter() for example, 'header' is set for all scripts even if it's not set in the $options array.

A couple other thoughts:

Would adding a comment above this line explaining 'force header' help?

Please look at the number of sites using these themes and the magic module and reconsider. By my count:

  • 1401 for the Aurora theme
  • 10797 for Omega 4.x
  • 2160 for the Magic module

Total: 14358.

star-szr’s picture

I should say 'header' is set for all scripts that do not specify a scope or that do not specify a different scope.

hass’s picture

That scope is not set has only one reason. A developer expect it in the header as this is the default. I do not need to set it as I know it lands in header. You guys abuse the page variable $header and as the name says it should be in header and not footer. You may like to convince maintainers to add their scripts intentionally to footer or add a header/footer setting to solve this. I have header/footer setting in every module where footer is supported. But you only break things and require me to double force header. No, this is nothing I support - not here and not in google_analytics where we have the same issue.

Please respect the core API and do not try to change it yourself (hacking core). If you are able to get this into core I reconsider the integration.

star-szr’s picture

Status: Needs review » Closed (won't fix)

I tried.

hass’s picture

Title: Add support for Force Header JS option (magic module compatibility) » Respect original JS scope
Project: Piwik Web Analytics » Omega
Category: Feature request » Bug report
Priority: Normal » Major
Status: Closed (won't fix) » Active

Moving queue. Maintainers of the themes must stop disrespecting the Core API.

May be broken:

  • Google Analytics (~400.000 installs)
  • Piwik (~13.000 installs)
hass’s picture

Issue summary: View changes
hass’s picture

Issue summary: View changes
hass’s picture

Issue summary: View changes
hass’s picture

Issue summary: View changes
hass’s picture

Version: 7.x-2.x-dev » 7.x-4.x-dev
hass’s picture

fubhy’s picture

@hass It looks like you did not check or do not understand what 'force header' is for.

It gives javascript files that *have* to remain in the header the option to tell these other modules and themes so while allowing the theme/module to proceed and optimize page speed by moving all other assets to the footer.

So your statement about "disrespecting core APIs" is completely false.

fubhy’s picture

I also do not understand your other statement about "hacking core". Every _alter hook implemented by module/theme is a core hack? :/

hass’s picture

I understood very well what 'force header' does. It does what 'header' has been made for.

My code defines to put js code in 'header' and these theme here moves it to 'footer'. What do you think is wrong? Yes, the theme that moves my header code to footer!

star-szr’s picture

@hass I really do not appreciate you turning my small feature request issue into your own personal vendetta. Please open a separate issue if you must continue down this path.

fubhy’s picture

I understood very well what 'force header' does. It does what 'header' has been made for.

No.

hass’s picture

@cottser: you missunderstand something. This is not a vendetta. No idea why you think this. You only pointed out a theme bug that need to be fixed.

@fubhy: enlighten me, please. You missed to comment on the more important part of my comment.

fubhy’s picture

Drupal defaults to rendering scripts in HEAD and 99% of the modules blindly make use of that because people apparently don't know better and the API is wrong in defaulting to 'header'. Only in special cases you actually want to have your script in the header. Although you keep calling this a "bug" I reckon you know about the implications of the HTTP spec and how document rendering works and especially how assets impact it so I am not going into more detail here.

Back to Drupal... Because it defaults to HEAD (which is a wrong default) the themes and modules listed here provide an *option* to fix that. So, in this case, using hook_js_alter() we override the scope of the script to footer unless 'force header' is set. We don't know if a module explicitly set 'header' or if it was added by the defaults, hence a new flag is needed to identify the subset of special libraries, like GA or others which need to stay in HEAD.

The most obvious way to solve this problem is to simply add the 'force header' flag for the scripts in question here. I don't even get why we are having this discussion. It's no big deal.

hass’s picture

I have 'header' set as scope in my modules. This means my scripts must show up in header. There is no reason for me to double set something to header by setting both 'force header' and 'header'. The bug here is that the theme moves everything to footer - in-depended of your performance optimization tryout. The performance issue is not my point.

I fully understand why you move JS stuff to footer, but you see here - this is a design fault. You cannot do this that simple way. If you think you need to require 'force header' from modules than you need to change Drupal core to allow you altering JS scopes before they are filled with the so named bad 'header' default. This would allow modules to add code to header, defaulting to footer without 'force header'. Aside of this I added inline code, no links that cause HTTP requests. Inline can safely stay in header I guess.

The only safe way how you should move JS to the footer automatically is with a white-list (not a black-list) and only if you know 100% for sure that the JS code can be moved to the footer and is therefore compatible with footer region. Defaulting everything to footer will break modules and is clearly a design bug in the theme alter logic. You can also add a theme configuration option that allow users to move something not white-listed to the footer manually. But I cannot support these users in my queues.

I propose you try to add an alter function to core https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_.... This will not cause any override of 'header' scope set by modules and you can set a 'footer' default. However I would still expect failures.

Example:

function drupal_js_defaults($data = NULL) {
  $defaults = array(
    'type' => 'file',
    'group' => JS_DEFAULT,
    'every_page' => FALSE,
    'weight' => 0,
    'scope' => 'header',
    'cache' => TRUE,
    'defer' => FALSE,
    'preprocess' => TRUE,
    'version' => NULL,
    'data' => $data,
  );

  // Allow other modules/themes to change the defaults.
  drupal_alter('drupal_js_defaults', $defaults);

  return $defaults;
}

Summary - change Drupal Core API if something is wrong and do not break modules, please.