KEMBAR78
JavaScript in Drupal 7: What developers need to know | KEY
JavaScript in Drupal 7:

WHAT DEVELOPERS NEED TO KNOW




                               October 24th, 2009
PROBLEM:

jQuery’s use of the $ can interfere with other
libraries.

D6:
$(document).ready(function(){

      ....

});


                                         October 24th, 2009
SOLUTION:

Wrap everthing in the following:


(function($) {

  ....

})(jQuery);




                                   October 24th, 2009
PROBLEM:

Not enough flexibility in how we can add js to our Drupal pages:

 - can’t fully control the ordering of js files

 - can’t load external js

D6:

drupal_add_js(‘path/to/some_js_file.js’, ‘module’, ‘header’);




                                                  October 24th, 2009
SOLUTION:

drupal_add_js() now allows you to add a weight value to each script
you’re adding:
  - JS_LIBRARY: Any libraries, settings, or jQuery plugins.
  - JS_DEFAULT: Any module-layer JavaScript.
  - JS_THEME: Any theme-layer JavaScript.

 drupal_add_js('jQuery(document).ready(function ()
{ alert("Hello!"); });', array('type' => 'inline', 'scope' => 'footer',
'weight' => 5);



                                                          October 24th, 2009
SOLUTION:

drupal_add_js() allows you to load external js files:

drupal_add_js('http://example.com/example.js', 'external');




                                                       October 24th, 2009
PROBLEM:

Some JavaScript code is being provided by core or some contrib
module but it’s not the most up-to-date version.




                                                 October 24th, 2009
SOLUTION:

hook_js_alter()

function hook_js_alter(&$javascript) {
  // Swap out jQuery to use an updated version of the library.
  $javascript['misc/jquery.js']['data'] = drupal_get_path('module',
'jquery_update') . '/jquery.js';
}




                                                             October 24th, 2009
Renderable arrays and #attached js:


function render_my_content() {
  $build['myelement'] = array(
    '#theme' => 'my_theme_function',
    '#myvar' => $myvar,
    '#attached' => array('js' => drupal_get_path('module', 'mymodule') .
'/myjs.js', 'css' => drupal_get_path('module', 'mymodule') . '/
styles.css'),
  );
  $output = drupal_render($build);
  return $output;
}




                                                      October 24th, 2009
PROBLEM:

There’s no standard way of adding collections of JavaScript and
CSS, such as jQuery plugins




                                                  October 24th, 2009
SOLUTION: Libraries
                      function system_library() {
                        ...
                        // Vertical Tabs.
                        $libraries['vertical-tabs'] = array(
                           'title' => 'Vertical Tabs',
                           'website' => 'http://drupal.org/node/323112',
                           'version' => '1.0',
hook_library()             'js' => array(
                              'misc/vertical-tabs.js' => array(),
                           ),
                           'css' => array(
                              'misc/vertical-tabs.css' => array(),
                           ),
                        );
                        ...
                        return $libraries;
                      }




                                                          October 24th, 2009
function mymodule_library() {
SOLUTION: Libraries     $libraries['mylibrary'] = array(
                           'title' => 'An Awesome Library',
                           'website' => 'http://example.com/library',
                           'version' => '3.1-beta1',
                           'js' => array(
                              // JavaScript settings may use the 'data' key.
                              array(
                                 'type' => 'setting',
                                 'data' => array('mylibrary' => TRUE),
hook_library()                ),
                           ),
                           'dependencies' => array(
                              // Require jQuery UI core by System module.
                              array('system' => 'ui'),
                              // Require our other library.
                              array('mymodule', 'library-1'),
                              // Require another library.
                              array('other_module', 'library-2'),
                           ),
                        );
                        return $libraries;
                      }


                                                          October 24th, 2009
SOLUTION: Libraries

                        function theme_vertical_tabs($variables) {
                          $element = $variables['element'];
                          // Add required JavaScript and Stylesheet.
                          drupal_add_library('system', 'vertical-
drupal_add_libarary()   tabs');

                          return '<div class="vertical-tabs-panes">' .
                        $element['#children'] . '</div>';
                        }




                                                  October 24th, 2009
PROBLEM:

AHAH forms make people want to jump out the window of very tall
buildings




                                               October 24th, 2009
AHAH in D6.... ugh!
function quicktabs_ahah() {
  $form_state = array('storage' => NULL, 'submitted' => FALSE);
  $form_build_id = $_POST['form_build_id'];
  $form = form_get_cache($form_build_id, $form_state);
  $args = $form['#parameters'];
  $form_id = array_shift($args);
  $form['#post'] = $_POST;
  $form['#redirect'] = FALSE;
  $form['#programmed'] = FALSE;
  $form_state['post'] = $_POST;
  drupal_process_form($form_id, $form, $form_state);
  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
  $qt_form = $form['qt_wrapper']['tabs'];
  unset($qt_form['#prefix'], $qt_form['#suffix']); // Prevent duplicate wrappers.
  $javascript = drupal_add_js(NULL, NULL, 'header');
  drupal_json(array(
    'status'   => TRUE,
    'data'     => theme('status_messages') . drupal_render($qt_form),
    'settings' => call_user_func_array('array_merge_recursive',
$javascript['setting']),
  ));
}


                                                                         October 24th, 2009
AJAX in D7.... :-)




function quicktabs_ajax($form, $form_state) {
  $form_tabs = $form['qt_wrapper']['tabs'];
  $output = drupal_render($form_tabs);
  return $output;
}




                                                October 24th, 2009
SOLUTION:

There’s now a framework for ajax in Drupal

Merlinofchaos has done all the hard work, so you don’t have to! :-)




                                                       October 24th, 2009
PROBLEM:

Ajax-loaded content doesn’t get behaviors attached to it if they
depend on Drupal.settings




                                                   October 24th, 2009
SOLUTION:

Drupal.attachBehaviors now takes a second parameter, which is the
local settings for the portion of the DOM it’s attaching behaviors to:

Drupal.attachBehaviors(context, settings)




                                                        October 24th, 2009
To have the settings available for your ajax-loaded content:

- your ajax callback must make a call to drupal_add_js to grab the
JavaScript for the output it’s rendering

- it must return the settings array as part of its response

- when your ajax success function makes a call to
Drupal.attachBehaviors, it must pass in the settings from the
response.




                                                    October 24th, 2009
function quicktabs_ajax_qtabs($qtid) {
  $tabpage = array(
    'type' => 'qtabs',
    'qtid' => $qtid,
  );

  $output = quicktabs_render_tabpage($tabpage);

  $scripts = drupal_add_js(NULL, NULL);
  $settings = call_user_func_array('array_merge_recursive', $scripts['settings']
['data']);
  drupal_json_output(array('status' => TRUE, 'data' => $output, 'settings' =>
$settings));
}




                                                             October 24th, 2009
Drupal.quicktabs.tab.prototype.success = function(response) {
  var result = Drupal.parseJson(response.data);
  this.container.append(Drupal.theme('quicktabsResponse', this,
result));
  Drupal.attachBehaviors(this.container, response.settings);
}




                                                 October 24th, 2009
Drupal.behaviors.quicktabs = {
  attach: function (context, settings) {
    $.extend(true, Drupal.settings, settings);
    $('.quicktabs_wrapper:not(.quicktabs-processed)',
context).addClass('quicktabs-processed').each(function(){
      Drupal.quicktabs.prepare(this);
    });
  }
}




                                               October 24th, 2009
jQuery UI is in core

- accordion            - progressbar   effects:

- datepicker           - resizable     - bounce

- dialog               - selectable    - explode

- draggable            - sortable      - fold

- droppable            - tabs          - pulsate



                                           October 24th, 2009
jQuery UI is in core
function render_accordion_block() {
  $build['myelement'] = array(
    '#theme' => 'my_accordion',
  );
  $build['myelement']['#attached']['library'][] = array('system',
'ui.accordion');
  $build['myelement']['#attached']['js'][] = array('data' =>
'(function($){$(function() { $("#accordion").accordion(); })})(jQuery);',
'type' => 'inline');
  $output = drupal_render($build);
  return $output;
}




                                                      October 24th, 2009
Miscellaneous Changes:

- Drupal.behaviors are now attached and detached

- drupal_to_js is now drupal_json_encode

- drupal_json is now drupal_json_output

- use jQuery.once() to attach a behaviour once




                                                   October 24th, 2009
QUESTIONS?




             October 24th, 2009

JavaScript in Drupal 7: What developers need to know

  • 1.
    JavaScript in Drupal7: WHAT DEVELOPERS NEED TO KNOW October 24th, 2009
  • 2.
    PROBLEM: jQuery’s use ofthe $ can interfere with other libraries. D6: $(document).ready(function(){ .... }); October 24th, 2009
  • 3.
    SOLUTION: Wrap everthing inthe following: (function($) { .... })(jQuery); October 24th, 2009
  • 4.
    PROBLEM: Not enough flexibilityin how we can add js to our Drupal pages: - can’t fully control the ordering of js files - can’t load external js D6: drupal_add_js(‘path/to/some_js_file.js’, ‘module’, ‘header’); October 24th, 2009
  • 5.
    SOLUTION: drupal_add_js() now allowsyou to add a weight value to each script you’re adding: - JS_LIBRARY: Any libraries, settings, or jQuery plugins. - JS_DEFAULT: Any module-layer JavaScript. - JS_THEME: Any theme-layer JavaScript. drupal_add_js('jQuery(document).ready(function () { alert("Hello!"); });', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5); October 24th, 2009
  • 6.
    SOLUTION: drupal_add_js() allows youto load external js files: drupal_add_js('http://example.com/example.js', 'external'); October 24th, 2009
  • 7.
    PROBLEM: Some JavaScript codeis being provided by core or some contrib module but it’s not the most up-to-date version. October 24th, 2009
  • 8.
    SOLUTION: hook_js_alter() function hook_js_alter(&$javascript) { // Swap out jQuery to use an updated version of the library. $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js'; } October 24th, 2009
  • 9.
    Renderable arrays and#attached js: function render_my_content() {   $build['myelement'] = array(     '#theme' => 'my_theme_function',     '#myvar' => $myvar,     '#attached' => array('js' => drupal_get_path('module', 'mymodule') . '/myjs.js', 'css' => drupal_get_path('module', 'mymodule') . '/ styles.css'),   );   $output = drupal_render($build);   return $output; } October 24th, 2009
  • 10.
    PROBLEM: There’s no standardway of adding collections of JavaScript and CSS, such as jQuery plugins October 24th, 2009
  • 11.
    SOLUTION: Libraries function system_library() { ... // Vertical Tabs. $libraries['vertical-tabs'] = array( 'title' => 'Vertical Tabs', 'website' => 'http://drupal.org/node/323112', 'version' => '1.0', hook_library() 'js' => array( 'misc/vertical-tabs.js' => array(), ), 'css' => array( 'misc/vertical-tabs.css' => array(), ), ); ... return $libraries; } October 24th, 2009
  • 12.
    function mymodule_library() { SOLUTION:Libraries $libraries['mylibrary'] = array( 'title' => 'An Awesome Library', 'website' => 'http://example.com/library', 'version' => '3.1-beta1', 'js' => array( // JavaScript settings may use the 'data' key. array( 'type' => 'setting', 'data' => array('mylibrary' => TRUE), hook_library() ), ), 'dependencies' => array( // Require jQuery UI core by System module. array('system' => 'ui'), // Require our other library. array('mymodule', 'library-1'), // Require another library. array('other_module', 'library-2'), ), ); return $libraries; } October 24th, 2009
  • 13.
    SOLUTION: Libraries function theme_vertical_tabs($variables) { $element = $variables['element']; // Add required JavaScript and Stylesheet. drupal_add_library('system', 'vertical- drupal_add_libarary() tabs'); return '<div class="vertical-tabs-panes">' . $element['#children'] . '</div>'; } October 24th, 2009
  • 14.
    PROBLEM: AHAH forms makepeople want to jump out the window of very tall buildings October 24th, 2009
  • 15.
    AHAH in D6....ugh! function quicktabs_ahah() {   $form_state = array('storage' => NULL, 'submitted' => FALSE);   $form_build_id = $_POST['form_build_id'];   $form = form_get_cache($form_build_id, $form_state);   $args = $form['#parameters'];   $form_id = array_shift($args);   $form['#post'] = $_POST;   $form['#redirect'] = FALSE;   $form['#programmed'] = FALSE;   $form_state['post'] = $_POST;   drupal_process_form($form_id, $form, $form_state);   $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);   $qt_form = $form['qt_wrapper']['tabs'];   unset($qt_form['#prefix'], $qt_form['#suffix']); // Prevent duplicate wrappers.   $javascript = drupal_add_js(NULL, NULL, 'header');   drupal_json(array(     'status'   => TRUE,     'data'     => theme('status_messages') . drupal_render($qt_form),     'settings' => call_user_func_array('array_merge_recursive', $javascript['setting']),   )); } October 24th, 2009
  • 16.
    AJAX in D7....:-) function quicktabs_ajax($form, $form_state) {   $form_tabs = $form['qt_wrapper']['tabs'];   $output = drupal_render($form_tabs);   return $output; } October 24th, 2009
  • 17.
    SOLUTION: There’s now aframework for ajax in Drupal Merlinofchaos has done all the hard work, so you don’t have to! :-) October 24th, 2009
  • 18.
    PROBLEM: Ajax-loaded content doesn’tget behaviors attached to it if they depend on Drupal.settings October 24th, 2009
  • 19.
    SOLUTION: Drupal.attachBehaviors now takesa second parameter, which is the local settings for the portion of the DOM it’s attaching behaviors to: Drupal.attachBehaviors(context, settings) October 24th, 2009
  • 20.
    To have thesettings available for your ajax-loaded content: - your ajax callback must make a call to drupal_add_js to grab the JavaScript for the output it’s rendering - it must return the settings array as part of its response - when your ajax success function makes a call to Drupal.attachBehaviors, it must pass in the settings from the response. October 24th, 2009
  • 21.
    function quicktabs_ajax_qtabs($qtid) {  $tabpage = array(     'type' => 'qtabs',     'qtid' => $qtid,   );   $output = quicktabs_render_tabpage($tabpage);   $scripts = drupal_add_js(NULL, NULL);   $settings = call_user_func_array('array_merge_recursive', $scripts['settings'] ['data']);   drupal_json_output(array('status' => TRUE, 'data' => $output, 'settings' => $settings)); } October 24th, 2009
  • 22.
    Drupal.quicktabs.tab.prototype.success = function(response){   var result = Drupal.parseJson(response.data);   this.container.append(Drupal.theme('quicktabsResponse', this, result));   Drupal.attachBehaviors(this.container, response.settings); } October 24th, 2009
  • 23.
    Drupal.behaviors.quicktabs = {  attach: function (context, settings) {     $.extend(true, Drupal.settings, settings);     $('.quicktabs_wrapper:not(.quicktabs-processed)', context).addClass('quicktabs-processed').each(function(){       Drupal.quicktabs.prepare(this);     });   } } October 24th, 2009
  • 24.
    jQuery UI isin core - accordion - progressbar effects: - datepicker - resizable - bounce - dialog - selectable - explode - draggable - sortable - fold - droppable - tabs - pulsate October 24th, 2009
  • 25.
    jQuery UI isin core function render_accordion_block() {   $build['myelement'] = array(     '#theme' => 'my_accordion',   );   $build['myelement']['#attached']['library'][] = array('system', 'ui.accordion');   $build['myelement']['#attached']['js'][] = array('data' => '(function($){$(function() { $("#accordion").accordion(); })})(jQuery);', 'type' => 'inline');   $output = drupal_render($build);   return $output; } October 24th, 2009
  • 26.
    Miscellaneous Changes: - Drupal.behaviorsare now attached and detached - drupal_to_js is now drupal_json_encode - drupal_json is now drupal_json_output - use jQuery.once() to attach a behaviour once October 24th, 2009
  • 27.
    QUESTIONS? October 24th, 2009