From 3f0cbfb11e26b8d9c319e9145ccb66116b8ea2e1 Mon Sep 17 00:00:00 2001 From: Gordon Heydon Date: Thu, 22 Apr 2010 18:31:06 -0700 Subject: [PATCH] * #87994 --- includes/common.inc | 96 +++++++++++++++++++++++++++++++++- misc/effect.js | 51 ++++++++++++++++++ modules/filter/filter.module | 58 +++++++++++++++----- modules/filter/filter.pages.inc | 2 +- modules/php/php.test | 4 +- modules/simpletest/tests/common.test | 8 +++ modules/system/system-behavior.css | 12 ++++ modules/system/system.module | 2 + 8 files changed, 214 insertions(+), 19 deletions(-) create mode 100644 misc/effect.js diff --git includes/common.inc includes/common.inc index 75953a0..a2e406b 100644 --- includes/common.inc +++ includes/common.inc @@ -3781,8 +3781,8 @@ function drupal_get_js($scope = 'header', $javascript = NULL) { * ); * @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 + * 'js', 'css', 'library', and 'effect' 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 @@ -3817,6 +3817,7 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch 'library' => array(), 'js' => array(), 'css' => array(), + 'effect' => array(), ); // Add the libraries first. @@ -3858,6 +3859,12 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch unset($elements['#attached'][$type]); } + // Add jQuery effects. + foreach ($elements['#attached']['effect'] as $effect) { + drupal_add_effect($effect); + } + unset($elements['#attached']['effect']); + // Add additional types of attachments specified in the render() structure. // Libraries, Javascript and CSS have been added already, as they require // special handling. @@ -4020,6 +4027,91 @@ function drupal_get_library($module, $name) { } /** + * Adds a jQuery effect to the page. + * + * This is used to invoke any jQuery method on a given element. The effects + * can be bound to user events (like click or change), or be executed once the + * element is ready. + * + * @param $options + * An associative array with the following keys defining the jQuery action + * being added: + * - selector: The jQuery selector for the element to apply the effect to. + * - effect: (optional) The name of the jQuery function to be called. This + * allows calling functions like "show", "hide", etc. If not provided, + * will default to the name of the library in use, through "library". + * - arguments: (optional) An array of arguments that are passed to the + * element during execution. + * - library: (optional) The name of the library to add, if desired. Some + * examples are "ui.dialog", "ui.accordion", "farbtastic", "once", etc. + * - module: (optional) When adding a library, this represents the name of + * the module that originally registered the library. Defaults to "system". + * - event: (optional) The name of the bound event the effect should be + * applied to the element. Defaults to once the element is "ready". Other + * possible events include "click", "change", "mouseenter", etc. + * - bound_element: (optional) When binding on an event other than ready, + * will be the element that the event is bound to. Defaults to what was + * passed into the "selector" argument. + * - is: (optional) Allows applying the effect only when the given condition + * is met. To read more about "is", visit the jQuery documentation at: + * http://docs.jquery.com/Traversing/is . + * - is_selector: (optional) When acting on a conditioning attribute through + * the "is" parameter, this argument represents a jQuery selector pointing + * to the element that will be checked. Defaults to the "bound_element". + * - return_value: (optional) The value which should be returned after the + * effect is applied to the bound element. Defaults to FALSE. + * - effects: (optional) An array of different effects to take on the given + * element. All parameters are inherited from the parent effect, but can be + * overriden by the child. + */ +function drupal_add_effect(array $options = array()) { + // Merge in the defaults. + $options += array( + 'module' => 'system', + 'event' => 'ready', + ); + + // Prepare the Effect Drupal behavior. + $added = &drupal_static(__FUNCTION__, FALSE); + if (!$added) { + $added = TRUE; + drupal_add_js('misc/effect.js'); + } + + // Allow multiple effects to be invoked on the element. + if (isset($options['effects'])) { + foreach ($options['effects'] as $effect) { + // The base elements are inherited from the parent effect so that the + // items do not have to be defined twice. + $effect = array_merge($options, $effect); + // Remove items that should not be inherited, and invoke the effect. + unset($effect['effects']); + drupal_add_effect($effect); + } + } + + // Add the depending library, if needed. + if (isset($options['library'])) { + drupal_add_library($options['module'], $options['library']); + + // The effect defaults to the associated library, if not explicitly defined. + if (!isset($options['effect'])) { + // Remove the "ui." prefix from jQuery UI widgets. + $options['effect'] = str_replace('ui.', '', $options['library']); + } + } + + // Add the settings so that the behaviors are attached to the elements. + if (isset($options['selector'])) { + $effect = $options['effect']; + // Remove all keys that are no JavaScript settings and add the settings. + unset($options['module'], $options['library'], $options['effects']); + $settings['effect'][$effect][] = $options; + drupal_add_js($settings, 'setting'); + } +} + +/** * Assist in adding the tableDrag JavaScript behavior to a themed table. * * Draggable tables should be used wherever an outline or list of sortable items diff --git misc/effect.js misc/effect.js new file mode 100644 index 0000000..7e8b543 --- /dev/null +++ misc/effect.js @@ -0,0 +1,51 @@ +// $Id$ +(function ($) { + +/** + * @file + * Provides the Effect Drupal behavior. + */ + +/** + * Attaches jQuery effects to page elements. + * + * This will go through all desired effects and apply them to the appropriate + * elements, taking the function arguments and bound events into consideration. + */ +Drupal.behaviors.effect = { + attach: function (context, settings) { + // Iterate through each desired jQuery effect and apply it to each of the + // desired elements. + $.each(settings.effect || {}, function (effect, effects) { + $.each(effects, function (index, options) { + // Apply the effect on ready state. + if (options.event == 'ready') { + $(options.selector, context).once('effect-' + effect + '-' + index, function() { + // Since we are calling the function with a dynamic set of + // arguments, we need to use .apply(). + var $element = $(this); + $element[effect].apply($element, options.arguments); + }); + } + // Apply the effect for a certain event. If no bound element is + // provided, use the originally selected item. + else { + $(options.bound_element || options.selector, context).once('effect-' + effect + '-' + options.event + '-' + index).bind(options.event, function() { + // Make sure the "is" condition is satisfied. + if (options.is ? $(options.is_selector ? options.is_selector : this).is(options.is) : true) { + // Since we are calling the function with a dynamic set of + // arguments, we need to use .apply(). + var $element = $(options.selector); + $element[effect].apply($element, options.arguments); + } + // Return the expected value, defaulting to false to override the + // default functionality of the effect. + return options.return_value || false; + }); + } + }); + }); + } +}; + +})(jQuery); diff --git modules/filter/filter.module modules/filter/filter.module index 2b4bddf..f2be8ae 100644 --- modules/filter/filter.module +++ modules/filter/filter.module @@ -59,9 +59,6 @@ function filter_theme() { 'text_format_wrapper' => array( 'render element' => 'element', ), - 'filter_tips_more_info' => array( - 'variables' => array(), - ), 'filter_guidelines' => array( 'variables' => array('format' => NULL), ), @@ -844,10 +841,48 @@ function filter_process_format($element) { $element['format']['help'] = array( '#type' => 'container', - '#theme' => 'filter_tips_more_info', '#attributes' => array('class' => array('filter-help')), '#weight' => 0, ); + $element['format']['help']['link'] = array( + '#type' => 'link', + '#title' => t('More information about text formats'), + '#href' => 'filter/tips', + '#options' => array( + 'attributes' => array('class' => array('filter-help-link')), + ), + ); + // Create a dialog box for the filter tips. + $element['format_help_tips'] = array( + '#type' => 'container', + '#id' => drupal_html_id('filter-tips'), + '#attributes' => array('class' => array('js-show')), + ); + $element['format_help_tips']['content'] = array( + '#theme' => 'filter_tips', + '#tips' => _filter_tips(-1, TRUE), + '#long' => TRUE, + ); + $element['format_help_tips']['#attached']['effect'][] = array( + 'library' => 'ui.dialog', + 'selector' => '#' . $element['format_help_tips']['#id'], + 'arguments' => array( + array( + 'width' => 720, + 'height' => 400, + 'autoOpen' => FALSE, + 'title' => t('Filter tips'), + ), + ), + 'effects' => array( + // When the more information link is clicked, open the dialog box. + array( + 'event' => 'click', + 'bound_element' => '.filter-help a.filter-help-link', + 'arguments' => array('open'), + ), + ), + ); // Lastly, disallow editing of this field if the user is not allowed to use // the stored and preselected text format. But only, if that format actually @@ -909,6 +944,10 @@ function filter_form_after_build($element, &$form_state) { break; default: + // Skip children that have no #value. + if (!isset($element[$key]['#value'])) { + continue; + } $current_parents[] = $key; form_set_value(array('#parents' => $current_parents), $element[$key]['#value'], $form_state); } @@ -1099,15 +1138,6 @@ function filter_dom_serialize_escape_cdata_element($dom_document, $dom_element, } /** - * Returns HTML for a link to the more extensive filter tips. - * - * @ingroup themeable - */ -function theme_filter_tips_more_info() { - return '

' . l(t('More information about text formats'), 'filter/tips') . '

'; -} - -/** * Returns HTML for guidelines for a text format. * * @param $variables @@ -1120,7 +1150,7 @@ function theme_filter_guidelines($variables) { $format = $variables['format']; $name = isset($format->name) ? '' : ''; - return '
' . $name . theme('filter_tips', array('tips' => _filter_tips($format->format, FALSE))) . '
'; + return '
' . $name . theme('filter_tips', array('tips' => _filter_tips($format->format, FALSE))) . '
'; } /** diff --git modules/filter/filter.pages.inc modules/filter/filter.pages.inc index 76ad21d..fb2b2ce 100644 --- modules/filter/filter.pages.inc +++ modules/filter/filter.pages.inc @@ -71,7 +71,7 @@ function theme_filter_tips($variables) { if (count($tiplist) > 0) { $output .= ''; } diff --git modules/php/php.test modules/php/php.test index caa2224..143c6f7 100644 --- modules/php/php.test +++ modules/php/php.test @@ -82,7 +82,7 @@ class PHPFilterTestCase extends PHPTestCase { $this->assertRaw(t('Basic page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.')); // Make sure that the PHP code shows up as text. - $this->assertNoText('print "SimpleTest PHP was executed!"', t("PHP code isn't displayed.")); + $this->assertNoText('print "SimpleTest PHP was executed!"', t('PHP code is not displayed.')); $this->assertText('SimpleTest PHP was executed!', t('PHP code has been evaluated.')); } } @@ -110,7 +110,7 @@ class PHPAccessTestCase extends PHPTestCase { // Make sure that the PHP code shows up as text. $this->drupalGet('node/' . $node->nid); - $this->assertText('print', t('PHP code was not evaluated.')); + $this->assertText('print "SimpleTest PHP was executed!"', t('PHP code is displayed.')); // Make sure that user doesn't have access to filter. $this->drupalGet('node/' . $node->nid . '/edit'); diff --git modules/simpletest/tests/common.test modules/simpletest/tests/common.test index 777b413..e686c08 100644 --- modules/simpletest/tests/common.test +++ modules/simpletest/tests/common.test @@ -1284,6 +1284,14 @@ class JavaScriptTestCase extends DrupalWebTestCase { $query_string = substr(variable_get('css_js_query_string', '0'), 0, 1); $this->assertRaw(drupal_get_path('module', 'node') . '/node.js?arg1=value1&arg2=value2&' . $query_string, t('Query string was appended correctly to js.')); } + + /** + * Tests the retrieval of libraries. + */ + function testGetLibrary() { + $farbtastic = drupal_get_library('common_test', 'farbtastic'); + $this->assertEqual($farbtastic['version'], '5.3', t('Retrieved a single library.')); + } } /** diff --git modules/system/system-behavior.css modules/system/system-behavior.css index 66e71a8..7eebe6b 100644 --- modules/system/system-behavior.css +++ modules/system/system-behavior.css @@ -266,6 +266,8 @@ div.password-confirm { } /** + * Hide elements only when JavaScript is enabled. + * * For anything you want to hide on page load when JS is enabled, so * that you can use the JS to control visibility and avoid flicker. */ @@ -274,6 +276,16 @@ html.js .js-hide { } /** + * Show elements only when JavaScript is enabled. + */ +.js-show { + display: none; +} +html.js .js-show { + display: inherit; +} + +/** * Hide elements from all users. * * Used for elements which should not be immediately displayed to any user. An diff --git modules/system/system.module modules/system/system.module index 28e2e7b..826cdc6 100644 --- modules/system/system.module +++ modules/system/system.module @@ -1211,6 +1211,8 @@ function system_library() { ), 'dependencies' => array( array('system', 'ui.widget'), + array('system', 'ui.draggable'), + array('system', 'ui.resizable'), ), ); $libraries['ui.draggable'] = array( -- 1.6.6.1