diff --git a/core/includes/common.inc b/core/includes/common.inc
index c9913a2..fc5fa52 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -6539,6 +6539,9 @@ function drupal_common_theme() {
'links' => array(
'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array()),
),
+ 'dropbutton' => array(
+ 'variables' => array('title' => NULL, 'links' => NULL, 'image' => FALSE, 'class' => NULL),
+ ),
'image' => array(
// HTML 4 and XHTML 1.0 always require an alt attribute. The HTML 5 draft
// allows the alt attribute to be omitted in some cases. Therefore,
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 2d1d375..88add35 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1691,6 +1691,93 @@ function theme_links($variables) {
}
/**
+ * Create a dropbutton menu.
+ *
+ * @param $title
+ * The text to place in the clickable area to activate the dropbutton. This
+ * text is indented to -9999px by default.
+ * @param $links
+ * A list of links to provide within the dropbutton, suitable for use
+ * in via Drupal's theme('links').
+ * @param $image
+ * If true, the dropbutton link is an image and will not get extra decorations
+ * that a text dropbutton link will.
+ * @param $class
+ * An optional class to add to the dropbutton's container div to allow you
+ * to style a single dropbutton however you like without interfering with
+ * other dropbuttons.
+ */
+function theme_dropbutton($variables) {
+ // Check to see if the number of links is greater than 1;
+ // otherwise just treat this like a button.
+ if (!empty($variables['links'])) {
+ $is_drop_button = (count($variables['links']) > 1);
+
+ // Add needed files
+ if ($is_drop_button) {
+ drupal_add_js('core/misc/dropbutton.js');
+ }
+
+ // Provide a unique identifier for every button on the page.
+ static $id = 0;
+ $id++;
+
+ // Wrapping div
+ $class = 'dropbutton-no-js';
+ $class .= ($is_drop_button) ? ' dropbutton' : '';
+ $class .= ' button';
+ if (!empty($variables['class'])) {
+ $class .= ($variables['class']) ? (' ' . implode(' ', $variables['class'])) : '';
+ }
+
+ $output = '';
+
+ $output .= '
'; // dropbutton
+ return $output;
+ }
+ else {
+ return '';
+ }
+}
+
+/**
* Returns HTML for an image.
*
* @param $variables
diff --git a/core/misc/dropbutton.js b/core/misc/dropbutton.js
new file mode 100644
index 0000000..9824c9e
--- /dev/null
+++ b/core/misc/dropbutton.js
@@ -0,0 +1,97 @@
+// $Id$
+/**
+ * @file
+ * Implement a simple, clickable dropbutton menu.
+ *
+ * See dropbutton.theme.inc for primary documentation.
+ *
+ * The javascript relies on four classes:
+ * - The dropbutton must be fully contained in a div with the class
+ * dropbutton. It must also contain the class dropbutton-no-js
+ * which will be immediately removed by the javascript; this allows for
+ * graceful degradation.
+ * - The trigger that opens the dropbutton must be an a tag wit hthe class
+ * dropbutton-link. The href should just be '#' as this will never
+ * be allowed to complete.
+ * - The part of the dropbutton that will appear when the link is clicked must
+ * be a div with class dropbutton-container.
+ * - Finally, dropbutton-hover will be placed on any link that is being
+ * hovered over, so that the browser can restyle the links.
+ *
+ * This tool isn't meant to replace click-tips or anything, it is specifically
+ * meant to work well presenting menus.
+ */
+
+(function ($) {
+
+Drupal.behaviors.dropbutton = {
+ attach: function () {
+ // Process buttons. All dropbuttons are buttons.
+ $('.button')
+ .once('button')
+ .removeClass('dropbutton-no-js');
+
+ // Process dropbuttons. Not all buttons are dropbuttons.
+ $('.dropbutton').once('dropbutton', function () {
+ var $dropbutton = $(this);
+ var $button = $dropbutton.find('.dropbutton-content');
+ var $secondaryActions = $button.find('li').not(':first');
+ var $twisty = $dropbutton.find(".dropbutton-link");
+ var open = false;
+ var hovering = false;
+ var timerID = 0;
+
+ var toggle = function (close) {
+ // if it's open or we're told to close it, close it.
+ if (open || close) {
+ // If we're just toggling it, close it immediately.
+ if (!close) {
+ open = false;
+ $secondaryActions.slideUp(100);
+ $dropbutton.removeClass('open');
+ }
+ else {
+ // If we were told to close it, wait half a second to make
+ // sure that's what the user wanted.
+ // Clear any previous timer we were using.
+ if (timerID) {
+ clearTimeout(timerID);
+ }
+ timerID = setTimeout(function () {
+ if (!hovering) {
+ open = false;
+ $secondaryActions.slideUp(100);
+ $dropbutton.removeClass('open');
+ }}, 500);
+ }
+ }
+ else {
+ // open it.
+ open = true;
+ $secondaryActions.animate({height: "show", opacity: "show"}, 100);
+ $dropbutton.addClass('open');
+ }
+ }
+ // Hide the secondary actions initially.
+ $secondaryActions.hide();
+
+ $twisty.click(function () {
+ toggle();
+ return false;
+ });
+
+ $dropbutton.hover(
+ function () {
+ hovering = true;
+ }, // hover in
+ function () { // hover out
+ hovering = false;
+ toggle(true);
+ return false;
+ }
+ );
+ });
+ }
+}
+
+})(jQuery);
diff --git a/core/modules/system/system.base.css b/core/modules/system/system.base.css
index 610d94d..ac91e72 100644
--- a/core/modules/system/system.base.css
+++ b/core/modules/system/system.base.css
@@ -286,3 +286,93 @@ section,
summary {
display: block;
}
+
+.dropbutton {
+ padding-right: 18px;
+ position: relative;
+ background-color: inherit;
+ border-style: solid;
+ border-width: 1px;
+ display: inline-block;
+ line-height: 1;
+}
+
+.dropbutton:hover {
+ cursor: pointer;
+}
+
+.dropbutton.open {
+ z-index: 200;
+}
+
+.dropbutton .dropbutton-content {
+ padding-bottom: 2px;
+ padding-top: 2px;
+}
+
+.dropbutton .dropbutton-content li,
+.dropbutton .dropbutton-content a {
+ display: block;
+}
+.dropbutton li {
+ line-height: 1.3333;
+}
+
+.dropbutton li a {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+
+.dropbutton .dropbutton-link {
+ bottom: 0;
+ display: block;
+ height: auto;
+ position: absolute;
+ right: 0;
+ text-indent: -9999px; /* LTR */
+ top: 0;
+ width: 17px;
+}
+
+.dropbutton .dropbutton-link a {
+ overflow: hidden;
+}
+
+.dropbutton .dropbutton-content ul {
+ margin: 0;
+ overflow: hidden;
+ list-style-image: none;
+ list-style-type: none;
+}
+
+.dropbutton.open li + li {
+ padding-top: 4px;
+}
+
+/**
+ * This creates the dropbutton arrow and inherits the link color
+ */
+.dropbutton-twisty {
+ border-bottom-color: transparent;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ border-style: solid;
+ border-width: 4px 4px 0;
+ line-height: 0;
+ right: 6px;
+ position: absolute;
+ top: 0.75em;
+}
+
+.dropbutton.open .dropbutton-twisty {
+ border-bottom: 4px solid;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ border-top-color: transparent;
+ top: 0.5em;
+}
+
+.dropbutton-no-js .dropbutton-twisty {
+ display: none;
+}
+