I call my block module 'meditation' (sorry if I don't use the right terms but I hope my meaning is clear).

Right before ending the hook_block I wrote some code to include Javascript. I got from an online example:

        drupal_add_js(drupal_get_path('module', 'meditation') .'/test.js');

        $setting = array(              'value' => t('s')        );

        drupal_add_js($setting, 'setting');

test.js:

  if(Drupal.settings.value)
      alert(Drupal.settings.value);
  else
      alert ('nothing');

It pops up the second alert so the file does include ok. But the setting does not work.

I tried a few variations of the $setting syntax and array structure. I also tried to dump out Drupal.settings but it is totally empty. Is there an option needing to be set that the examples didn't make obvious?

I checked many forums and online examples also but this was the simplest, so sorry if there is an obvious answer. Thank you for any helpful information.

Comments

jaypan’s picture

You should namespace your settings:

$settings = array('value' => 'something');
drupal_add_js(array('mediation' => $settings), 'setting');

This should give you the value you want at Drupal.settings.mediation.value

Contact me to contract me for D7 -> D10/11 migrations.

jbhangoo’s picture

You might have guessed this would solve it as I did too. I actually had it that way originally.

I changed to the example above, thinking it would simplify the problem. But Drupal.settings is completely empty either way.

jaypan’s picture

Look at the page source. A couple of lines before the closing </head> tag, you should see something that looks something like this:

<!--//--><![CDATA[//><!--
jQuery.extend(Drupal.settings, { "basePath": "/", /* a bunch more code */});
//--><!]]>

In there, try to find the reference to your settings. That way you can track whether or not they are properly being added to the page.

Edit: also, read nevets post below - maybe you are executing your code right away when the script is loaded, which will be before the settings have loaded.

Contact me to contract me for D7 -> D10/11 migrations.

nevets’s picture

Try implementing your code as a behavior

Drupal.behaviors.mediation = function (context) {
  if(Drupal.settings.mediation.value)
      alert(Drupal.settings.mediation.value);
  else
      alert ('nothing');
};

This will insure the settings are "loaded" by the time your code runs.

jbhangoo’s picture

This is a great suggestion to improve the quality of the coding. I actually did have it written this way in an earlier test, but the Drupal.settings object was still empty.

About jQuery.extend:
I did find the line. Thank you for that insight! I did not even know about that.

That line is very long on my site since I have installed other modules I plan to use later, but it is there.

If I copy it into test.js, now I see the setting works! But stranger than that, even after I undo copying in that line, it still works! Note that all caching and optimization has been disabled for testing purpose.

I saw that I must de-reference the value using Drupal.settings[0].meditation

So, I don't know why, but it is working now. Thanks to both of you for your time and thought.

<!--//--><![CDATA[//><!--
jQuery.extend(Drupal.settings, { 
    "basePath": "/",
    "googleanalytics": { "trackOutgoing": 1, "trackMailto": 1, "trackDownload": 1, "trackDownloadExtensions": "7z|aac|arc|arj|asf|asx|avi|bin|csv|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls|xml|z|zip" }, 
    "lightbox2": { "rtl": 0, "file_path": "/(\\w\\w/)sites/default/files", "default_image": "/sites/all/modules/lightbox2/images/brokenimage.jpg", "border_size": 10, "font_color": "000", "box_color": "fff", "top_position": "", "overlay_opacity": "0.8", "overlay_color": "000", "disable_close_click": 1, "resize_sequence": 0, "resize_speed": 400, "fade_in_speed": 400, "slide_down_speed": 600, "use_alt_layout": 0, "disable_resize": 0, "disable_zoom": 0, "force_show_nav": 0, "show_caption": 1, "loop_items": 0, "node_link_text": "View Image Details", "node_link_target": 0, "image_count": "Image !current of !total", "video_count": "Video !current of !total", "page_count": "Page !current of !total", "lite_press_x_close": "press \x3ca href=\"#\" onclick=\"hideLightbox(); return FALSE;\"\x3e\x3ckbd\x3ex\x3c/kbd\x3e\x3c/a\x3e to close", "download_link_text": "Download Original", "enable_login": false, "enable_contact": false, "keys_close": "c x 27", "keys_previous": "p 37", "keys_next": "n 39", "keys_zoom": "z", "keys_play_pause": "32", "display_image_size": "", "image_node_sizes": "()", "trigger_lightbox_classes": "", "trigger_lightbox_group_classes": "", "trigger_slideshow_classes": "", "trigger_lightframe_classes": "", "trigger_lightframe_group_classes": "", "custom_class_handler": 0, "custom_trigger_classes": "", "disable_for_gallery_lists": true, "disable_for_acidfree_gallery_lists": true, "enable_acidfree_videos": true, "slideshow_interval": 5000, "slideshow_automatic_start": true, "slideshow_automatic_exit": true, "show_play_pause": true, "pause_on_next_click": false, "pause_on_previous_click": true, "loop_slides": false, "iframe_width": 600, "iframe_height": 400, "iframe_border": 1, "enable_video": 0 }, 
    "views_accordion": { "views-accordion-accordian-block_1": { "keeponeopen": 0, "startopen": 1, "rowstartopen": "0", "speed": 1, "disablecloseothers": 0, "grouping": 0, "togglelinks": 0, "autocycle": 0, "autocyclespeed": 2000, "display": "views-accordion-accordian-block_1", "usegroupheader": 0, "enableheaderlinks": 0, "header": "views-field-title" } }, 
    "0": { "meditation": { "value": "s" } } 
                                });
//--><!]]> 
roper.’s picture

You can't just copy the Drupal settings array into your JS file, that array can be different on every page load.
The following should work fine. If it's not we need to find the real issue rather than resorting to copying the whole settings structure.

function meditation_block($op = 'list', $delta = 0, $edit = array()) {
  ...
  $settings = array('value' => 'something');
  drupal_add_js(array('meditation' => $settings), 'setting');
  ...
}

In your module's included JS:

Drupal.behaviors.meditation = function (context) {
  if (Drupal.settings.meditation.value) {
    alert(Drupal.settings.meditation.value);
  }
  else  {
    alert('nothing');
  }
}

Both of those snippets were provided above, but I noticed a naming discrepancy that may have been your problem. In some places 'mediation' was used instead of 'meditation' (note the extra 't' needed).

jbhangoo’s picture

The typo was given by the person who commented, suggesting a different approach. It is not in my code.

I see your point: if I try to access any members of Drupal.settings I get "undefined".

jaypan’s picture

Show us your full js code.

Contact me to contract me for D7 -> D10/11 migrations.

jbhangoo’s picture

This is a test module to simplify the problem. The javascript references the settings perfectly through Drupal.settings[0] but fails on just Drupal.settings. But if I understand right, the array index may change later, so this is not the right solution.

I hope my jQuery is not the problem. I have installed jQuery Update and check the Status Report.

Thanks for any help this might show.

<?php

/**
 * @file
 * This is a block that calls javascript.
 */

/**
 * @defgroup jstest Block
 *
 */

/**
 * Implementation of hook_block().
 *
 * This hook both declares to Drupal what blocks are provided by the module, and
 * generates the contents of the blocks themselves.
 */
function jstest_block($op = 'list', $delta = '', $edit = array()) {
  // The $op parameter determines what piece of information is being requested.
  switch ($op) {
    case 'list':
      // If $op is "list", we just need to return a list of block descriptions.
      // This is used to provide a list of possible blocks to the administrator;
      // end users will not see these descriptions.
      $blocks['configurable-text'] = array(
        'info'       => t('jstest'),
      );
      // A block can provide default settings. In this case we'll enable the
      // block and make it visible only on the 'node/*' pages.
      $blocks['empty'] = array(
        'info'       => t('jstest'),
        'status'     => TRUE,
        'weight'     => 0,
        'visibility' => 1,
        'pages'      => 'node/*',
      );
      return $blocks;
    case 'configure':
      // If $op is "configure", we need to provide the administrator with a
      // configuration form. The $delta parameter tells us which block is being
      // configured. In this example, we'll allow the administrator to customize
      // the text of the first block.
      $form = array();
      if ($delta == 'configurable-text') {
        // All we need to provide is a text field, Drupal will take care of
        // the other block configuration options and the save button.
        $form['jstest_string'] = array(
          '#type' => 'textfield',
          '#title' => t('it is a jstest'),
          '#size' => 20,
          '#description' => t('This string will appear in the jstest block.'),
          '#default_value' => variable_get('jstest_string',  t('Select from the list of jstests.')),
        );
      }
      return $form;
    case 'save':
      // If $op is "save", we need to save settings from the configuration form.
      // Since the first block is the only one that allows configuration, we
      // need to check $delta to make sure we only save it.
      if ($delta == 'configurable-text') {
        // Have Drupal save the string to the database.
        variable_set('jstest_string', $edit['jstest_string']);
      }
      return;
    case 'view':
      // If $op is "view", then we need to generate the block for display
      // purposes. The $delta parameter tells us which block is being requested.
      switch ($delta) {
        case 'configurable-text':
          // The subject is displayed at the top of the block. Note that it
          // should be passed through t() for translation.
          $block['subject'] = t('jstests for test');
          // The content of the block comes from jstest_contents
          $block['content'] = jstest_contents(1);
          break;
        case 'empty':
          $block['subject'] = t('Title of block #2');
          $block['content'] = jstest_contents(2);
          break;
      }
      return $block;
  }
}

/**
 * A block content function.
 */
function jstest_contents($which_block) {

  switch ($which_block) {
    case 1:

        // Javascript start
        drupal_add_js(drupal_get_path('module', 'jstest') .'/test.js');
        // pass val to the JS
        $setting = array(
            array ('jstest' =>
              array('val' => 'w')
                  )
        );
        // pass variables to javascript
        drupal_add_js($setting, 'setting');
        // Javascript end

        $dir = drupal_get_path('module','jstest');

        variable_set('jstest_string',  t('<div id="t"></div>'));
        return variable_get('jstest_string', t('ss'));

    case 2:
      // In this case, Drupal will not display the block at all.
      return;
  }
}

/**
 * @} End of "defgroup jstest.
 */
jaypan’s picture

You've got one too many arrays in there. It should be:

$setting = array('jstest' => array('val' => 'w'));

You had:

$setting = array(array('jstest' => array('val' => 'w')));

Contact me to contract me for D7 -> D10/11 migrations.

jbhangoo’s picture

That was it! I had done so many variations of this value that I completely lost track of it.

I will add the features from the other full module to this working skeleton.

Thank you for the many helpful reviewers! Very helpful to get multiple insights.