Take the situation where no modules added javascript to your theme. So, $scripts has no value. Then, you want to add javascript to your theme via the template.php file. You do something like:

function phptemplate_preprocess_page(&$vars) {
  drupal_add_js(path_to_theme() .'/myscript.js', 'theme');
  $vars['scripts'] = drupal_get_js();
}

This should add your javascript to the page as well as drupal.js and jquery.js. But, it doesn't

The reason is that in template_proprocess_page $variables['scripts'] is set equal to drupal_get_js(). When drupal_get_js() is called it builds the $javascript array in drupal_add_js() so it isn't empty when your drupal_add_js() is run to add your theme javascript and therefore drupal.js and jquery.js are not added to it.

Comments

mfer’s picture

Status: Active » Needs review
StatusFileSize
new1.66 KB

My first pass at a patch for this. Only building the $javascript array if there is data to populate it.

mfer’s picture

StatusFileSize
new1.66 KB

My first pass at a patch for this. Only building the $javascript array if there is data to populate it.

mfer’s picture

StatusFileSize
new2.67 KB

Another version with a little less logic.

gábor hojtsy’s picture

Status: Needs review » Needs work

Hrm, I looked at this code, and have a few questions / observations:

1. Why isn't the header scope properly initialized? Your first call to drupal_add_js() should trigger the if (isset($data) && empty($javascript)) { line in drupal_add_js(). This is not changed with your patch either. You now do if (isset($data)) { if (empty($javascript)) { which should do the same. I don't understand this.

2. This part could probably be reworked to use the isset($scope) wrapper, and then do if (isset($javascript[$scope])) inside. But then this function is documented to return an array in all cases, so why do you return an empty string and not an empty array?

-  if (isset($scope)) {
+  if (isset($javascript[$scope])) {
     return $javascript[$scope];
   }
+  elseif (!isset($javascript[$scope]) && isset($scope)) {
+    return '';
+  }

3. Please use diff -up so we see which functions the changes reside in.

gábor hojtsy’s picture

Priority: Critical » Normal
Status: Needs work » Postponed (maintainer needs more info)

OK, no change in logic in the patch as I said, so I don't see this is critical or changes anything in the logic at all.

mfer’s picture

Assigned: Unassigned » mfer
Priority: Normal » Critical
StatusFileSize
new2.74 KB

@Gábor - I think this is critical because without a change drupal_add_js won't add jquery.js or drupal.js after template_preprocess_page [1]. This can cause problems for themes wanting to add javascript. Currently, in functions in template.php you would need to either manually add the javascript html to the $scripts (which won't go through javascript preprocessing) or you need to do a drupal_add_js for jquery.js and drupal.js.

This is because drupal_get_js is called in template_preprocess_page. drupal_get_js calls drupal_add_js with a scope but no data causing

  if (isset($scope) && !isset($javascript[$scope])) {
    $javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array());

to happen. This populates the $javascript array so that when drupal_add_js is called again

 if (isset($data) && empty($javascript)) {
    $javascript['header'] = array(
      'core' => array(
        'misc/jquery.js' => array('cache' => TRUE, 'defer' => FALSE, 'preprocess' => TRUE),
        'misc/drupal.js' => array('cache' => TRUE, 'defer' => FALSE, 'preprocess' => TRUE),
      ),
      'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array(),
    );
  }

doesn't happen.

The attached patch matches the functionality of D5 to add drupal.js and jquery.js any time drupal_add_js is called with data. It, also, checks if a $javascript[$scope] is set and only returns data if it is. This removes some 'Undefined index' messages. $javascript[$scope] is only populated if there is data now where before it was always populated.

Responding to #4

Why isn't the header scope properly initialized? Your first call to drupal_add_js() should trigger the if (isset($data) && empty($javascript)) { line in drupal_add_js(). This is not changed with your patch either. You now do if (isset($data)) { if (empty($javascript)) { which should do the same. I don't understand this.

You are right. What I did ended up removing one isset($data) call. It went from:

if (isset($data) && empty($javascript)) {
...
}
if (isset($data)) {
  ...
}

to

if (isset($data)) {
  if (empty($javascript)) {
    ...
  }
  ...
}

This part could probably be reworked to use the isset($scope) wrapper, and then do if (isset($javascript[$scope])) inside. But then this function is documented to return an array in all cases, so why do you return an empty string and not an empty array?

Included both of these in this patch.

[1] http://drupal.org/files/theme_flow_6_0.pdf

gábor hojtsy’s picture

Status: Postponed (maintainer needs more info) » Needs review
dvessel’s picture

Status: Needs review » Reviewed & tested by the community

This is a confusing bug and if left as is would be bad for themes.

mfer is right. Due to the way drupal_add_js get's called without the $data param from drupal_get_js causes the static $javascript to wipe killing jquery and drupal.js.

Blocking them within a "isset($data)" works.

gábor hojtsy’s picture

Status: Reviewed & tested by the community » Fixed

Well, I did not see the flow, so thanks for clarifying and reviewing. Also the latest patch fixes my other concerns, so thanks, committed.

Anonymous’s picture

Status: Fixed » Closed (fixed)

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