diff --git a/core/misc/dropbutton/dropbutton.base-rtl.css b/core/misc/dropbutton/dropbutton.base-rtl.css index 64684f5..be6fd6c 100644 --- a/core/misc/dropbutton/dropbutton.base-rtl.css +++ b/core/misc/dropbutton/dropbutton.base-rtl.css @@ -1,12 +1,11 @@ + /** - * @file dropbutton.base-rtl.css + * @file + * Base RTL styles for dropbuttons. */ /** * The dropbutton arrow. - * - * The arrow is created using border on a zero-width, zero-height span. - * The arrow inherits the link color, but can be overridden with border colors. */ .dropbutton-link { left: 0; @@ -18,9 +17,7 @@ } .dropbutton-multiple .dropbutton-widget { left: auto; - right: 0; -} -.dropbutton-multiple .dropbutton-widget { padding-left: 2em; padding-right: 0; + right: 0; } diff --git a/core/misc/dropbutton/dropbutton.base.css b/core/misc/dropbutton/dropbutton.base.css index 326c015..8eca580 100644 --- a/core/misc/dropbutton/dropbutton.base.css +++ b/core/misc/dropbutton/dropbutton.base.css @@ -1,6 +1,10 @@ + +/** + * @file + * Base styles for dropbuttons. + */ + /** - * @file dropbutton.base.css - * * When a dropbutton has only one option, it is simply a button. */ .dropbutton-wrapper, @@ -19,7 +23,7 @@ .dropbutton-widget { display: inline-block; } -/* ul styles are over-scoped in core, so this selector needs weight parity */ +/* UL styles are over-scoped in core, so this selector needs weight parity. */ .dropbutton-widget .dropbutton-content { list-style-image: none; list-style-type: none; diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js index 58ebbc1..ec62757 100644 --- a/core/misc/dropbutton/dropbutton.js +++ b/core/misc/dropbutton/dropbutton.js @@ -1,9 +1,3 @@ -/** - * @file dropbutton.js - * - * See dropbutton.theme.inc for primary documentation. - */ - (function ($, Drupal, window) { "use strict"; @@ -24,13 +18,13 @@ /** * A DropButton presents an HTML list as a button with a primary action. * - * Secondary actions - all actions beyond the first in the list - are presented - * in a dropdown list accessible through a toggle arrow associated with the - * button. - * - * @dropbutton {DOMElement}: An HTMLListElement. + * All secondary actions beyond the first in the list are presented in a + * dropdown list accessible through a toggle arrow associated with the button. * - * @options {Object}: A list of options including: + * @param {DOMElement} dropbutton + * An HTMLListElement. + * @param {Object} options + * A list of options including: * - title: The text inside the toggle link element. This text is hidden from * visual UAs. */ @@ -70,12 +64,12 @@ function DropButton (dropbutton, settings) { * Render the dropbutton view. */ build: function (options) { - // Save the id and class attributes so that they can be applied to the + // Save the ID and class attributes so that they can be applied to the // widget wrapper below. options.id = this.$list.attr('id') || ''; options['class'] = this.$list.attr('class').split(' ') || []; options['class'].push('dropbutton-wrapper'); - // Remove the class and id attributes. The values of these attributes + // Remove the class and ID attributes. The values of these attributes // will be applied to the dropbutton wrapper. this.$list.removeAttr('class id'); // Mark-up the list with dropbutton structure. @@ -109,6 +103,7 @@ function DropButton (dropbutton, settings) { 'click.dropbutton': $.proxy(this, 'toggleClickHandler') }, '.dropbutton-link'); }, + hoverIn: function () { // Clear any previous timer we were using. if (this.timerID) { @@ -116,20 +111,24 @@ function DropButton (dropbutton, settings) { } this.isHovered = true; }, + hoverOut: function () { this.isHovered = false; this.toggle(); }, + toggleClickHandler: function (event) { event.preventDefault(); var closeIt = (this.isOpen) ? true : false; this.toggle(closeIt); }, + /** * Toggle the dropbutton open and closed. * - * @param closeIt {Boolean}: (optional) Force the dropbutton to close by - * passing true or to close by passing false. + * @param {Boolean} closeIt + * (optional) Force the dropbutton to close by passing true or to close by + * passing false. */ toggle: function (closeIt) { // Open or close the dropbutton immediately if closeIt is defined. @@ -144,10 +143,12 @@ function DropButton (dropbutton, settings) { this.timerID = window.setTimeout($.proxy(this, 'close'), 500); } }, + close: function () { this.isOpen = false; this.$dropbutton.removeClass('open'); }, + open: function () { this.isOpen = true; this.$dropbutton.addClass('open'); @@ -157,7 +158,7 @@ function DropButton (dropbutton, settings) { /** * A toggle is an interactive element often bound to a click handler. * - * @param Object options: + * @param Object options * - String title: (optional) The HTML anchor title attribute and text for the * inner span element. * @@ -167,12 +168,13 @@ function DropButton (dropbutton, settings) { Drupal.theme.toggle = function (options) { return '' + options.title + ''; }; + /** * A wrapping DOM fragment representing a dropbutton widget. * - * @param Object options: - * - String id: (optional) An id to be applied to the outer wrapping div. - * - Array class: (optional) Classes to be applied to the outer wrapping div. + * @param Object options + * - String id: (optional) An ID to apply to the outer wrapping div. + * - Array class: (optional) Classes to apply to the outer wrapping div. * * @return String * A string representing a DOM fragment. diff --git a/core/misc/dropbutton/dropbutton.theme-rtl.css b/core/misc/dropbutton/dropbutton.theme-rtl.css index 27eb994..a5c6c4e 100644 --- a/core/misc/dropbutton/dropbutton.theme-rtl.css +++ b/core/misc/dropbutton/dropbutton.theme-rtl.css @@ -1,5 +1,7 @@ + /** - * @file dropbutton.theme-rtl.css + * @file + * General RTL styles for dropbuttons. */ .dropbutton-multiple .dropbutton-content { diff --git a/core/misc/dropbutton/dropbutton.theme.css b/core/misc/dropbutton/dropbutton.theme.css index 1360a90..2e52c1c 100644 --- a/core/misc/dropbutton/dropbutton.theme.css +++ b/core/misc/dropbutton/dropbutton.theme.css @@ -1,6 +1,9 @@ + /** - * @file dropbutton.theme.css + * @file + * General styles for dropbuttons. */ + .dropbutton-wrapper { cursor: pointer; min-height: 2em; diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module index 6187361..91a22c1 100644 --- a/core/modules/system/tests/modules/theme_test/theme_test.module +++ b/core/modules/system/tests/modules/theme_test/theme_test.module @@ -58,6 +58,19 @@ function theme_test_menu() { 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); + + $items['theme-test'] = array( + 'title' => 'Theme test', + 'page callback' => 'system_admin_menu_block_page', + 'access callback' => TRUE, + 'file path' => drupal_get_path('module', 'system'), + 'file' => 'system.admin.inc', + ); + $items['theme-test/list/operations'] = array( + 'title' => 'Operations', + 'page callback' => '_theme_test_list_operations', + 'access callback' => TRUE, + ); return $items; } @@ -146,3 +159,78 @@ function theme_test_preprocess_html(&$variables) { function theme_theme_test_foo($variables) { return $variables['foo']; } + +/** + * Page callback for manual testing of operation links. + */ +function _theme_test_list_operations() { + $build = array( + '#theme' => 'table', + '#header' => array('Label', 'Created', 'Operations'), + '#rows' => array(), + ); + // Add an item with a very long label, using common operations. + $build['#rows']['long']['label'] = l('An item with a very insanely long label, which offers quite a couple of common operations', 'item/long'); + $build['#rows']['long']['created'] = format_interval(3200); + $build['#rows']['long']['operations'] = array( + 'data' => array( + '#theme' => 'dropbutton__node_operations', + '#links' => array( + 'edit' => array( + 'title' => 'edit', + 'href' => 'item/long/edit', + ), + 'disable' => array( + 'title' => 'disable', + 'href' => 'item/long/disable', + ), + 'clone' => array( + 'title' => 'clone', + 'href' => 'item/long/clone', + ), + 'delete' => array( + 'title' => 'delete', + 'href' => 'item/long/delete', + ), + ), + ), + ); + + // Add another item, using common operations. + $build['#rows']['another']['label'] = l('Another item, using common operations', 'item/another'); + $build['#rows']['another']['created'] = format_interval(8600); + $build['#rows']['another']['operations'] = $build['#rows']['long']['operations']; + + // Add an item with only one operation. + $build['#rows']['one']['label'] = l('An item with only one operation', 'item/one'); + $build['#rows']['one']['created'] = format_interval(12400); + $build['#rows']['one']['operations'] = array( + 'data' => array( + '#theme' => 'dropbutton__node_operations', + '#links' => array( + 'edit' => array( + 'title' => 'edit', + 'href' => 'item/long/edit', + ), + ), + ), + ); + + // Add an item that can only be viewed. + $build['#rows']['view']['label'] = l('An item that can only be viewed', 'item/view'); + $build['#rows']['view']['created'] = format_interval(12400); + $build['#rows']['view']['operations'] = array( + 'data' => array( + '#theme' => 'dropbutton__node_operations', + '#links' => array(), + ), + ); + + // Add an item for which the default operation is denied. + $build['#rows']['denied']['label'] = l('An item for which the default operation is denied', 'item/denied'); + $build['#rows']['denied']['created'] = format_interval(18600); + $build['#rows']['denied']['operations'] = $build['#rows']['long']['operations']; + unset($build['#rows']['denied']['operations']['data']['#links']['edit']); + + return $build; +}