Commit a539b0e0 authored by Dries's avatar Dries

- Patch by #565496 by dropcube, pwolanin: changed Allow dynamic attaching of...

- Patch by #565496 by dropcube, pwolanin: changed Allow dynamic attaching of other types of stuff to render() structures.
parent 2431df84
......@@ -292,7 +292,7 @@ function ajax_process_form($element) {
// we avoid the problem by checking if the JavaScript has already been added.
if (!isset($js_added[$element['#id']]) && (isset($element['#ajax']['callback']) || isset($element['#ajax']['path'])) && isset($element['#ajax']['event'])) {
drupal_add_library('system', 'form');
$element['#attached_js'] = array('misc/ajax.js');
$element['#attached']['js'][] = 'misc/ajax.js';
$ajax_binding = array(
'url' => isset($element['#ajax']['callback']) ? url('system/ajax') : url($element['#ajax']['path']),
......
......@@ -3203,14 +3203,31 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
}
/**
* Adds all the attached libraries, JavaScript and CSS to the page.
* Add to the page all structures attached to a render() structure.
*
* @param $libraries
* An array of depending libraries to be added.
* @param $js
* An array of JavaScript components to add.
* @param $css
* An array of cascading stylesheets to add.
* Libraries, JavaScript, CSS and other types of custom structures are attached
* to elements using the #attached property. The #attached property contains an
* associative array, where the keys are the the types of the structure, and
* the value the attached data. For example:
* @code
* $build['#attached'] = array(
* 'js' => array(drupal_get_path('module', 'taxonomy') . '/taxonomy.js'),
* 'css' => array(drupal_get_path('module', 'taxonomy') . '/taxonomy.css'),
* );
* @endcode
*
* 'js', 'css', and 'library' are types that get special handling. For any
* other kind of attached data, the array key must be the full name of the
* callback function and each value an array of arguments. For example:
*
* @code
* $build['#attached']['drupal_set_header'] = array(
* array('Content-Type', 'application/rss+xml; charset=utf-8'),
* );
* @endcode
*
* @param $elements
* The structured array describing the data being rendered.
* @param $weight
* The default weight of JavaScript and CSS being added. This is only applied
* to the stylesheets and JavaScript items that don't have an explicit weight
......@@ -3223,12 +3240,26 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
* Will return FALSE if there were any missing library dependencies. TRUE will
* be returned if all library dependencies were met.
*
* @see drupal_add_library(), drupal_render()
* @see drupal_add_library().
* @see drupal_add_js().
* @see drupal_add_css().
* @see drupal_render().
*/
function drupal_process_attached(array $libraries = array(), array $js = array(), array $css = array(), $weight = JS_DEFAULT, $dependency_check = FALSE) {
function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_check = FALSE) {
// If there is nothing to process then return.
if (empty($elements['#attached'])) {
return;
}
// Add defaults to the special attached structures that should be processed differently.
$elements['#attached'] += array(
'library' => array(),
'js' => array(),
'css' => array(),
);
// Add the libraries first.
$success = TRUE;
foreach ($libraries as $library) {
foreach ($elements['#attached']['library'] as $library) {
if (drupal_add_library($library[0], $library[1]) === FALSE) {
$success = FALSE;
// Exit if the dependency is missing.
......@@ -3237,10 +3268,13 @@ function drupal_process_attached(array $libraries = array(), array $js = array()
}
}
}
unset($elements['#attached']['library']);
// Add both the JavaScript and the CSS.
foreach (array('js' => $js, 'css' => $css) as $type => $items) {
foreach ($items as $data => $options) {
// The parameters for drupal_add_js() and drupal_add_css() require special
// handling.
foreach (array('js', 'css') as $type) {
foreach ($elements['#attached'][$type] as $data => $options) {
// If the value is not an array, it's a filename and passed as first
// (and only) argument.
if (!is_array($options)) {
......@@ -3259,7 +3293,20 @@ function drupal_process_attached(array $libraries = array(), array $js = array()
}
call_user_func('drupal_add_' . $type, $data, $options);
}
unset($elements['#attached'][$type]);
}
// Add additional types of attachments specified in the render() structure.
// Libraries, Javascript and CSS have been added already, as they require
// special handling.
foreach ($elements['#attached'] as $callback => $options) {
if (function_exists($callback)) {
foreach ($elements['#attached'][$callback] as $args) {
call_user_func_array($callback, $args);
}
}
}
return $success;
}
......@@ -3292,7 +3339,12 @@ function drupal_add_library($module, $name) {
if (!isset($added[$module][$name])) {
if ($library = drupal_get_library($module, $name)) {
// Add all components within the library.
$added[$module][$name] = drupal_process_attached($library['dependencies'], $library['js'], $library['css'], JS_LIBRARY, TRUE);
$elements['#attached'] = array(
'library' => $library['dependencies'],
'js' => $library['js'],
'css' => $library['css'],
);
$added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE);
}
else {
// Requested library does not exist.
......@@ -4141,12 +4193,9 @@ function drupal_render(&$elements) {
}
}
// Add additional libraries, CSS and JavaScript associated with this element.
drupal_process_attached(
isset($elements['#attached_library']) ? $elements['#attached_library'] : array(),
isset($elements['#attached_js']) ? $elements['#attached_js'] : array(),
isset($elements['#attached_css']) ? $elements['#attached_css'] : array()
);
// Add additional libraries, CSS, JavaScript an other custom
// attached data associated with this element.
drupal_process_attached($elements);
$prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
$suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
......@@ -4252,12 +4301,9 @@ function drupal_render_cache_get($elements) {
$bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
if (!empty($cid) && $cache = cache_get($cid, $bin)) {
// Add additional libraries, CSS and JavaScript associated with this element.
drupal_process_attached(
isset($cache->data['#attached_library']) ? $cache->data['#attached_library'] : array(),
isset($cache->data['#attached_js']) ? $cache->data['#attached_js'] : array(),
isset($cache->data['#attached_css']) ? $cache->data['#attached_css'] : array()
);
// Add additional libraries, JavaScript, CSS and other data attached
// to this element.
drupal_process_attached($cache->data);
// Return the rendered output.
return $cache->data['#markup'];;
}
......@@ -4284,12 +4330,8 @@ function drupal_render_cache_set($markup, $elements) {
}
$data['#markup'] = $markup;
// Persist additional CSS and JavaScript files associated with this element.
foreach (array('css', 'js', 'library') as $kind) {
if (!empty($elements['#attached_' . $kind])) {
$data['#attached_' . $kind] = $elements['#attached_' . $kind];
}
}
// Persist attached data associated with this element.
$data['#attached'] = $elements['#attached'];
$bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
$expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : CACHE_PERMANENT;
cache_set($cid, $data, $bin, $expire);
......@@ -4412,6 +4454,7 @@ function element_basic_defaults() {
'#title' => '',
'#attributes' => array(),
'#required' => FALSE,
'#attached' => array(),
);
}
......
......@@ -2253,9 +2253,9 @@ function form_process_fieldset(&$element, &$form_state) {
$element['#group_members'] = &$form_state['groups'][$parents];
// Contains form element summary functionalities.
$element['#attached_js']['misc/form.js'] = array('weight' => JS_LIBRARY + 1);
$element['#attached']['js']['misc/form.js'] = array('weight' => JS_LIBRARY + 1);
if (!empty($element['#collapsible'])) {
$element['#attached_js']['misc/collapse.js'] = array();
$element['#attached']['js'][] = 'misc/collapse.js';
}
return $element;
......
......@@ -445,7 +445,9 @@ function _book_add_form_elements(&$form, $node) {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'book') . '/book.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'book') . '/book.js'),
),
'#tree' => TRUE,
'#attributes' => array('class' => array('book-outline-form')),
);
......
......@@ -148,22 +148,24 @@ function color_scheme_form(&$form_state, $theme) {
'#title' => t('Color set'),
'#options' => $info['schemes'],
'#default_value' => $current,
// Add Farbtastic color picker.
'#attached_library' => array(
array('system', 'farbtastic'),
),
// Add custom CSS.
'#attached_css' => array(
$base . '/color.css' => array('preprocess' => FALSE),
),
// Add custom JavaScript.
'#attached_js' => array(
$base . '/color.js',
array(
'data' => array('color' => array(
'reference' => color_get_palette($theme, TRUE),
)),
'type' => 'setting',
'#attached' => array(
// Add Farbtastic color picker.
'library' => array(
array('system', 'farbtastic'),
),
// Add custom CSS.
'css' => array(
$base . '/color.css' => array('preprocess' => FALSE),
),
// Add custom JavaScript.
'js' => array(
$base . '/color.js',
array(
'data' => array(
'color' => array('reference' => color_get_palette($theme, TRUE)),
),
'type' => 'setting',
),
),
),
);
......
......@@ -590,7 +590,7 @@ function comment_node_page_additions($node) {
$comments = comment_load_multiple($cids);
comment_prepare_thread($comments);
$build = comment_build_multiple($comments);
$build['#attached_css'][] = drupal_get_path('module', 'comment') . '/comment.css';
$build['#attached']['css'][] = drupal_get_path('module', 'comment') . '/comment.css';
$build['pager']['#theme'] = 'pager';
$additions['comments'] = $build;
}
......@@ -940,7 +940,9 @@ function comment_form_node_type_form_alter(&$form, $form_state) {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'comment') . '/comment-node-form.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'comment') . '/comment-node-form.js'),
),
);
$form['comment']['comment_default_mode'] = array(
'#type' => 'checkbox',
......@@ -1006,7 +1008,9 @@ function comment_form_alter(&$form, $form_state, $form_id) {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'comment') . '/comment-node-form.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'comment') . '/comment-node-form.js'),
),
'#weight' => 30,
);
$comment_count = isset($node->nid) ? db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() : 0;
......@@ -1614,7 +1618,7 @@ function comment_form(&$form_state, $comment) {
$node = node_load($comment->nid);
if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
$form_state['#attached_js'][] = drupal_get_path('module', 'comment') . '/comment.js';
$form_state['#attached']['js'][] = drupal_get_path('module', 'comment') . '/comment.js';
}
$comment = (array) $comment;
......
......@@ -490,7 +490,7 @@ function field_attach_form($obj_type, $object, &$form, &$form_state, $langcode =
// Add custom weight handling.
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$form['#attached_css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$form['#attached']['css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$form['#pre_render'][] = '_field_extra_weights_pre_render';
$form['#extra_fields'] = field_extra_fields($bundle);
......@@ -1090,7 +1090,7 @@ function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode =
// Add custom weight handling.
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$output['#attached_css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$output['#attached']['css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$output['#pre_render'][] = '_field_extra_weights_pre_render';
$output['#extra_fields'] = field_extra_fields($bundle);
......
......@@ -71,9 +71,7 @@ function file_field_settings_form($field, $instance) {
$defaults = field_info_field_settings($field['type']);
$settings = array_merge($defaults, $field['settings']);
$form = array(
'#attached_js' => array(drupal_get_path('module', 'file') . '/file.js'),
);
$form['#attached']['js'][] = drupal_get_path('module', 'file') . '/file.js';
$form['display_field'] = array(
'#type' => 'checkbox',
......@@ -119,9 +117,7 @@ function file_field_settings_form($field, $instance) {
function file_field_instance_settings_form($field, $instance) {
$settings = $instance['settings'];
$form = array(
'#attached_js' => array(drupal_get_path('module', 'file') . '/file.js'),
);
$form['#attached']['js'][] = drupal_get_path('module', 'file') . '/file.js';
$form['max_filesize'] = array(
'#type' => 'textfield',
......
......@@ -50,8 +50,10 @@ function file_elements() {
'#upload_validators' => array(),
'#upload_location' => NULL,
'#extended' => FALSE,
'#attached_css' => array($file_path . '/file.css'),
'#attached_js' => array($file_path . '/file.js'),
'#attached' => array(
'css' => array($file_path . '/file.css'),
'js' => array($file_path . '/file.js'),
),
);
return $elements;
......
......@@ -15,7 +15,9 @@ function image_style_list() {
$styles = image_styles();
$page['image_style_list'] = array(
'#markup' => theme('image_style_list', $styles),
'#attached_css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
'#attached' => array(
'css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
),
);
return $page;
......@@ -40,7 +42,9 @@ function image_style_form(&$form_state, $style) {
$form_state['image_style'] = $style;
$form = array(
'#tree' => TRUE,
'#attached_css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
'#attached' => array(
'css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
),
);
// Allow the name of the style to be changed.
......@@ -313,7 +317,9 @@ function image_effect_form(&$form_state, $style, $effect) {
$form = array(
'#tree' => TRUE,
'#attached_css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
'#attached' => array(
'css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array('preprocess' => FALSE)),
),
);
if (function_exists($effect['form callback'])) {
$form['data'] = call_user_func($effect['form callback'], $effect['data']);
......
......@@ -448,7 +448,9 @@ function menu_edit_menu(&$form_state, $type, $menu = array()) {
'#maxsize' => MENU_MAX_MENU_NAME_LENGTH_UI,
'#description' => t('This text will be used to construct the URL for the menu. The name must contain only lowercase letters, numbers and hyphens, and must be unique.'),
'#required' => TRUE,
'#attached_js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
'#attached' => array(
'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
),
);
}
......
......@@ -412,7 +412,9 @@ function menu_form_alter(&$form, $form_state, $form_id) {
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'menu') . '/menu.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'menu') . '/menu.js'),
),
'#tree' => TRUE,
'#weight' => -2,
'#attributes' => array('class' => array('menu-item-form')),
......
......@@ -101,7 +101,9 @@ function node_type_form(&$form_state, $type = NULL) {
'#maxlength' => 32,
'#required' => TRUE,
'#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the <em>add new content</em> page for this content type. This name must contain only lowercase letters, numbers, and underscores. Underscores will be converted into hyphens when constructing the URL of the <em>add new content</em> page. This name must be unique.'),
'#attached_js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
'#attached' => array(
'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
),
);
}
else {
......
......@@ -172,7 +172,9 @@ function node_form(&$form_state, $node) {
// Collapsed by default when "Create new revision" is unchecked
'#collapsed' => !$node->revision,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'node') . '/node.js'),
),
'#weight' => 20,
);
$form['revision_information']['revision'] = array(
......@@ -198,7 +200,9 @@ function node_form(&$form_state, $node) {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'node') . '/node.js'),
),
'#weight' => 90,
);
$form['author']['name'] = array(
......@@ -229,7 +233,9 @@ function node_form(&$form_state, $node) {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'node') . '/node.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'node') . '/node.js'),
),
'#weight' => 95,
);
$form['options']['status'] = array(
......
......@@ -234,7 +234,9 @@ function path_form_alter(&$form, $form_state, $form_id) {
'#collapsible' => TRUE,
'#collapsed' => empty($path),
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'path') . '/path.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'path') . '/path.js'),
),
'#access' => user_access('create url aliases'),
'#weight' => 30,
);
......
......@@ -896,14 +896,10 @@ class JavaScriptTestCase extends DrupalWebTestCase {
}
/**
* Tests the addition of libraries through the #attached_library property.
* Tests the addition of libraries through the #attached['library'] property.
*/
function testAttachedLibrary() {
$element = array(
'#attached_library' => array(
array('system', 'farbtastic'),
)
);
$element['#attached']['library'][] = array('system', 'farbtastic');
drupal_render($element);
$scripts = drupal_get_js();
$this->assertTrue(strpos($scripts, 'misc/farbtastic/farbtastic.js'), t('The attached_library property adds the additional libraries.'));
......
......@@ -3101,8 +3101,10 @@ function system_page_build(&$page) {
if (system_run_cron_image_access()) {
$page['page_bottom']['run_cron'] = array(
// Trigger cron run via AJAX.
'#attached_js' => array(
'(function($){ $.get(' . drupal_to_js(url('system/run-cron-image')) . '); })(jQuery);' => array('type' => 'inline', 'scope' => 'header'),
'#attached' => array(
'js' => array(
'(function($){ $.get(' . drupal_to_js(url('system/run-cron-image')) . '); })(jQuery);' => array('type' => 'inline', 'scope' => 'header'),
),
),
// Trigger cron run for clients not supporting JavaScript (fall-back).
'#markup' => theme('system_run_cron_image', 'system/run-cron-image'),
......
......@@ -151,7 +151,9 @@ function taxonomy_form_vocabulary(&$form_state, $edit = array()) {
'#maxlength' => 255,
'#description' => t('The unique machine readable name for this vocabulary, used for theme templates, can only contain lowercase letters, numbers and underscores.'),
'#required' => TRUE,
'#attached_js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
'#attached' => array(
'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
),
);
$form['help'] = array(
'#type' => 'textfield',
......
......@@ -61,12 +61,14 @@ function toolbar_build() {
$module_path = drupal_get_path('module', 'toolbar');
$build = array(
'#theme' => 'toolbar',
'#attached_js' => array(
$module_path . '/toolbar.js',
array('data' => 'misc/jquery.cookie.js', 'weight' => JS_LIBRARY + 2),
),
'#attached_css' => array(
$module_path . '/toolbar.css',
'#attached'=> array(
'js' => array(
$module_path . '/toolbar.js',
array('data' => 'misc/jquery.cookie.js', 'weight' => JS_LIBRARY + 2),
),
'css' => array(
$module_path . '/toolbar.css',
),
),
);
......
......@@ -76,7 +76,9 @@ function tracker_page($account = NULL, $set_title = FALSE) {
'#rows' => $rows,
'#header' => array(t('Type'), t('Post'), t('Author'), t('Replies'), t('Last updated')),
'#theme' => 'table',
'#attached_css' => array(drupal_get_path('module', 'tracker') . '/tracker.css' => array('preprocess' => FALSE)),
'#attached' => array(
'css' => array(drupal_get_path('module', 'tracker') . '/tracker.css' => array('preprocess' => FALSE)),
),
);
$page['pager'] = array(
'#theme' => 'pager',
......
......@@ -69,8 +69,8 @@ function upload_admin_settings() {
'#type' => 'fieldset',
'#title' => t('General settings'),
'#collapsible' => TRUE,
'#attached_css' => array(
drupal_get_path('module', 'upload') . '/upload.admin.css',
'#attached'=> array(
'css' => array(drupal_get_path('module', 'upload') . '/upload.admin.css'),
),
);
$form['settings_general']['upload_max_resolution'] = array(
......
......@@ -231,7 +231,9 @@ function upload_form_alter(&$form, $form_state, $form_id) {
'#collapsible' => TRUE,
'#collapsed' => empty($node->files),
'#group' => 'additional_settings',
'#attached_js' => array(drupal_get_path('module', 'upload') . '/upload.js'),
'#attached' => array(
'js' => array(drupal_get_path('module', 'upload') . '/upload.js'),
),
'#description' => t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.'),
'#weight' => 30,
);
......
......@@ -651,7 +651,7 @@ function user_admin_permissions($form_state, $rid = NULL) {
}
$form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
$form['#attached_js'] = array(drupal_get_path('module', 'user') . '/user.permissions.js');
$form['#attached']['js'][] = drupal_get_path('module', 'user') . '/user.permissions.js';
return $form;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment