How to modify static javascript data in Drupal

We can add javascript or javascript settings in drupal by calling drupal_add_js(), in some cases you may want to remove some javascript you add earlier.
There is no built in function like drupal_remove_js() to do that.

The same applies to javascript settings which are stored Drupal.settings, what if we want to remove some settings that are added in previous processes? Adding a setting multiple times might have some unexpected consequences.

Javascript settings are used when you want to pass server data to javascript in the front end. For example if I want to pass a pair of geo coordinates from database to map initialization function in javascript, I would like to save coordinates in Drupal.settings then in behavior attach function to use them.

Adding server data to javascript settings:

// set the central point
  $lonlat = array(
      'lon' => $lon,
      'lat' => $lat,
  );
// add it to Drupal.settings
drupal_add_js(array(‘mySetting’ => array('center'=> $lonlat)), array('type' => 'setting'));

All javascripts and settings of a request are stored in a static data store($javascript), here is what happens when a javascript setting is added by drupal_add_js(),

  case 'setting':
        // All JavaScript settings are placed in the header of the page with
        // the library weight so that inline scripts appear afterwards.
        $javascript['settings']['data'][] = $data;
        break;

As you can see drupal_add_js() does not check if the same settings has already existed, it just simply appends it to $javascript[‘settings’][‘data’] array, adding a setting multiple times will end up copies of settings in static javascript array $javascript.

This only happens to settings, for javascripts it is keyed by javascript name, it will not have multiple copies.

When javascript is finally output to page in drupal_get_js():

case 'setting':
        $js_element = $element;
        $js_element['#value_prefix'] = $embed_prefix;
        $js_element['#value'] = 'jQuery.extend(Drupal.settings, ' . drupal_json_encode(drupal_array_merge_deep_array($item['data'])) . ");";
        $js_element['#value_suffix'] = $embed_suffix;
        $output .= theme('html_tag', array('element' => $js_element));
        break;

It does do some array merging, so you will not get two copies in Drupal.settings, but it is hard to predict which version of setting in $javascript actually made its way to Drupal.settings. and it is not an ideal situation to have multiple copies in $javascript in the first place.

Ideally drupal_add_js() would have prevented this by checking the existence of a settings before it is added.

Also We cannot find any built in functions that allow us to modify static $javascript. Here I want to share with you a function that I did to remove a customer setting from $javascript.


function  _remove_js_settings($settingKey)
{
  $javascript = &drupal_static('drupal_add_js');

  foreach ($javascript['settings']['data'] as $key => $item)
  {
    if (array_key_exists($settingKey, $item)) {
      unset($javascript['settings']['data'][$key]);
    }
  }

  return $javascript;
}

The only trick is calling &drupal_static() rather than calling drupal_add_js() as the former gives you a pointer and later is giving same list as a copy, the list you get from drupal_add_js() is a copy of static data, so changes to the copy are not persisted to static data store.

I am sure from this example you can work out how to remove javascript or even change css settings from its static cache, bearing in mind that css is stored at ‘drupal_add_css’

[Added 18 Oct 2013]

If a setting does need to have multiple values, it is better to put them in a keyed array, a  good example is system settings.ajax which is keyed by element id

$element['#attached']['js'][] = array(
      'type' => 'setting',
      'data' => array('ajax' => array($element['#id'] => $settings)),
 );

Tags:

This entry was posted on Thursday, June 27th, 2013 at 4:25 am and is filed under PHP. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “How to modify static javascript data in Drupal”

  1. Mohan says:

    Good Job!

Leave a Reply

*