From 07d22613683feee0c761bcf979d5724e3f53772d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?"J.=20Rene=CC=81e=20Beach"?= <splendidnoise@gmail.com>
Date: Mon, 3 Sep 2012 23:42:00 -0400
Subject: [PATCH] Issue #1137920 by jessebeach, kathryn531: implement redesign
 of the administration toolbar so that it displays well on
 screens of any size.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

commit 4ef16ea3c7640f12f203af127d35cb5ac3520836
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Mon Sep 3 23:34:55 2012 -0400

    Issue #1137920 by jessebeach: Patched up the flexiPanda plugin enough to post the changes to the issue queue.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 8af3f8658e15ac19045efd15835f09a09faaaeab
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sat Sep 1 17:15:27 2012 -0400

    Issue #1137920 by jessebeach: The basics of the flexiPanda plugin are in place.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 434c01817080bcf3f13488cd8ab49ee5a87988c3
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sat Sep 1 16:44:33 2012 -0400

    Issue #1137920 by jessebeach: The main menu now prints all of the links under the menu, not just the second level links.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit a4508bac9ea0fad70a26f040a601d2cd33b0fce3
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 16:18:19 2012 -0400

    Issue #1137920 by jessebeach: Further adjustments to the side tray CSS.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 720440c6125ae944ebf53d1b0e82c078c4a4ce46
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 15:55:07 2012 -0400

    Issue #1137920 by jessebeach: Further refinements to the CSS for the side tray.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit b76d48bfff76ea00cb906225f9ce58fd5553e22a
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 13:58:23 2012 -0400

    Issue #1137920 by jessebeach: Removed references to attached CSS from the hook_view. These attachments are now made in hook_library_info in the module.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 8b904aa347fead82cf932a1613abbe005f111590
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 10:31:52 2012 -0400

    Issue #1137920 by jessebeach: Renamed toolbar.admin.css to toolbar.base.css.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 66fed06f9b72a0fca2b475b5475bf879b14ed04a
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 10:30:46 2012 -0400

    Issue #1137920 by jessebeach: Removed styling from the shortcut module that targets the Toolbar module.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit c99a6b914e57d2665e581fd008306f47924c19d9
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 10:27:57 2012 -0400

    Issue #1137920 by jessebeach: I messed up the position of the toolbar-bar. Fixed it.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 5e2eb94a42b087a0e2b054b0ae47e3ad49e29c1f
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 31 10:19:55 2012 -0400

    Issue #1137920 by jessebeach: Shortcuts are now integrated into the side tray.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit a74024709c85622ee42e617c475e031a8107af78
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 16:15:51 2012 -0400

    Issue #1137920 by jessebeach: removed drop shadows from the toolbar and tray.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 94d8a2a983f00a49b30744404fe6117cf809b39b
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 14:17:57 2012 -0400

    Issue #1137920 by jessebeach: Experimenting with placing the toolbar in page_top or page_bottom. Going with page_bottom for now.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit da8e338e41d431deaacf2e8aa9b7b7218e6eba20
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 14:05:44 2012 -0400

    Issue #1137920 by jessebeach: Split the Toolbar CSS out into admin and theme. Removed Toolbar-targeted styling from the Shortcut module.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 60c416e4b6eb3e1f49b13dc940c0b1dd81b0c497
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 11:18:09 2012 -0400

    Issue #1137920 by jessebeach: Toolbar was moved from page_top to page_bottom. Updating the Shortcut module to reflect this.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 8d4aae61d64f4505b2b598e59a8aa1151ad2cd9f
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 10:19:11 2012 -0400

    Issue #1137920 by jessebeach: Changed references to CSS and JS files to point to the new directories. Added CSS files for .admin.css and .theme.css.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 57be37580132fc056f85b906cb974a7fcd7c9f4a
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 10:17:37 2012 -0400

    Issue #1137920 by jessebeach: Moved the toolbar from the page_top to the page_bottom region.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 5deb13437e378ac59598f3180c283ea60dbd7578
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 10:10:31 2012 -0400

    Issue #1137920 by jessebeach: moved CSS and JS files to their own directory.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 381f81ae1dc8c4078f0f7eb363aaf637095ba4f1
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Thu Aug 30 10:03:49 2012 -0400

    Issue #1137920 by jessebeach: Changed padding to margin to create the gap for the side pull menu tray.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 8c3f39f68a035a0149876fd6ef7cb78dabc8a759
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 14:48:42 2012 -0400

    Issue #1137920 by jessebeach: The admin tray now slides side to side.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit a6c65e4f8c5e87b46aeb4dbccc25a02389ab5e67
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 14:00:07 2012 -0400

    Issue 1137920 by jessebeach: Added a missing 'html' property to the options passed to theme_link that creates the menu tray button.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit a284438645558db7fa1e489713cc2d51fd6a5240
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 13:55:04 2012 -0400

    Issue #1137920 by jessebeach: added a @todo to move the computeOffsetTop method in tableheader.js to drupal.js.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit b706cf3d8f3db23e133fa704b1b3632dda411774
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 13:54:25 2012 -0400

    Issue #1137920 by jessebeach: The tray menu now positions itself correctly.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit f1225fd94433bae513e24106a0c16ded6249d809
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 13:25:26 2012 -0400

    Issue #1137920 by jessebeach: The toolbar drawer toggling action has been refactored to sue the properties of the Toolbar object, not raw DOM queries.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 84737ecc5769543105cb72770199627598b7b329
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Sun Aug 26 12:49:48 2012 +0200

    Issue #1137920 by jessebeach: Refactored the toolbar.js file to use an object for the bar and tray of the toolbar instead of bare JS constructs.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 94bd66eafb33b26494150f9153748a18f370dd46
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 17:46:21 2012 +0200

    Issue #1137920 by Kathryn531: Style updates to the existing toolbar

commit 66cee8b7370783dcdef34650ce75b983afef39bb
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 17:43:03 2012 +0200

    Issue #1137920 by Kathryn531: Sample look & feel of how the search filter will function (no submit button since updates happen on key events, sample close button included)

commit 707852807f6c7f81d7090e032c33a7a65ee42a9e
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 24 16:43:11 2012 +0200

    Issue #1137920 by jessebeach: side tray now toggles up and down. Precursor to the side sliding.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit f87de721d0becb6979ed5ebf9d0c2471020c66bd
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 24 16:24:45 2012 +0200

    Issue #1137920 by jessebeach: Added a tray toggle.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 6f1b4a36f5d54d0b326a84bf70f74f78465a10b8
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 15:35:48 2012 +0200

    Issue #1137920 by Kathryn531: Added textfield and link to appear as a search button for the filtering component in the toolbar tray.

commit b03fdfef844e92eb4b7825edd1dac3ec0d278f7f
Author: J. Renée Beach <splendidnoise@gmail.com>
Date:   Fri Aug 24 14:31:17 2012 +0200

    Issue #11337920 by jessebeach: refactored the toolbar.js to use an object Drupal.ToolBar.

    Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>

commit 47831518b69170c3782636acdf0d2f4693e2a3cf
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 14:05:02 2012 +0200

    Issue #1137920 by Kathryn531: Scoping CSS selectors to maintain original styling when main menu links are shown in wide layouts, but apply unique styling when displayed via the new toolbar tray.

commit 4c18076deeaef8a2cf14c698d45e36e1278418d0
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 13:08:08 2012 +0200

    Issue #1137920 by Kathryn531: Missed the template file. Adding it as well to previous commit.

commit 727df9fd5cbc7c7c8efa04793d5a9456a2c21ba8
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 13:07:38 2012 +0200

    Issue #1137920 by Kathryn531: Restructuring markup of toolbar so the toolbar-menu items appear below the main bar with Toggle, home, shortcuts, etc...

commit 3f7e695b230cec3edf1a97e004d6f1ad1e31bb2c
Author: Kathryn Cornelius <kathryn@amazeelabs.com>
Date:   Fri Aug 24 11:42:54 2012 +0200

    Issue #1137920 by Kathryn531: Added a temporary placeholder link in the new toolbar menu for tray toggle

Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>
---
 core/misc/tableheader.js                           |    1 +
 .../ui/menus/flexipanda/css/jquery.flexipanda.css  |  112 +++
 core/misc/ui/menus/flexipanda/jquery.flexipanda.js | 1037 ++++++++++++++++++++
 core/modules/shortcut/shortcut.base.css            |    6 -
 core/modules/shortcut/shortcut.module              |    4 +-
 core/modules/shortcut/shortcut.theme.css           |   51 -
 core/modules/system/system.module                  |   16 +
 core/modules/toolbar/css/toolbar.base-rtl.css      |   26 +
 core/modules/toolbar/css/toolbar.base.css          |   88 ++
 core/modules/toolbar/css/toolbar.theme-rtl.css     |   12 +
 core/modules/toolbar/css/toolbar.theme.css         |  210 ++++
 core/modules/toolbar/images/toolbar.png            |  Bin 0 -> 506 bytes
 core/modules/toolbar/js/toolbar.js                 |  240 +++++
 core/modules/toolbar/toolbar-rtl.css               |   37 -
 core/modules/toolbar/toolbar.css                   |  129 ---
 core/modules/toolbar/toolbar.js                    |  115 ---
 core/modules/toolbar/toolbar.module                |  115 ++-
 core/modules/toolbar/toolbar.png                   |  Bin 558 -> 0 bytes
 core/modules/toolbar/toolbar.tpl.php               |   18 +-
 19 files changed, 1819 insertions(+), 398 deletions(-)
 create mode 100644 core/misc/ui/menus/flexipanda/css/jquery.flexipanda.css
 create mode 100644 core/misc/ui/menus/flexipanda/jquery.flexipanda.js
 create mode 100644 core/modules/toolbar/css/toolbar.base-rtl.css
 create mode 100644 core/modules/toolbar/css/toolbar.base.css
 create mode 100644 core/modules/toolbar/css/toolbar.theme-rtl.css
 create mode 100644 core/modules/toolbar/css/toolbar.theme.css
 create mode 100644 core/modules/toolbar/images/toolbar.png
 create mode 100644 core/modules/toolbar/js/toolbar.js
 delete mode 100644 core/modules/toolbar/toolbar-rtl.css
 delete mode 100644 core/modules/toolbar/toolbar.css
 delete mode 100644 core/modules/toolbar/toolbar.js
 delete mode 100644 core/modules/toolbar/toolbar.png

diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index 364cad2..dceb71f 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -133,6 +133,7 @@ $.extend(TableHeader, {
 
   /**
    * Sum all [data-offset-top] values and cache it.
+   * @todo move this out of tableheader.js into a move generic place like drupal.js.
    */
   computeOffsetTop: function () {
     var $offsets = $('[data-offset-top]');
diff --git a/core/misc/ui/menus/flexipanda/css/jquery.flexipanda.css b/core/misc/ui/menus/flexipanda/css/jquery.flexipanda.css
new file mode 100644
index 0000000..d2cc2bb
--- /dev/null
+++ b/core/misc/ui/menus/flexipanda/css/jquery.flexipanda.css
@@ -0,0 +1,112 @@
+/** 
+* @file
+* Default dropdown behavior definitions.
+*/
+
+/* @group Behavior */
+
+.fp-wrapper {
+  position: relative;
+  overflow: hidden;
+}
+.fp-list {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+.fp-item {
+  display: block;
+}
+.fp-box {
+  position: relative;
+}
+.fp-dormant {
+	display: none;
+}
+.fp-calculate {
+  display: block !important;
+  visibility: hidden !important;
+  width: 100% !important;
+}
+.fp-trail > .fp-list { /* Show the sub-menus */
+  display: block;
+}
+.fp-active > .fp-list {
+  z-index: 51; /* Pull the active trail li's above the other li's */
+}
+.fp-wrapper .fp-box {
+  display: block;
+  line-height: 1em; /* this prevents the value "normal" from being returned as the line-height */
+  width: auto;
+}
+.fp-link {
+  display: block;
+}
+.fp-handle {
+  bottom: 0;
+  display: block;
+  height: 100%;
+  position: absolute;
+  right: 0;
+  top: 0;
+  width: 60px;
+  z-index: 1;
+}
+.fp-handle + * {
+  margin-right: 60px;
+}
+.fp-back .fp-handle {
+  left: 0;
+  right: auto;
+}
+.fp-back .fp-handle + * {
+  margin-left: 60px;
+  margin-right: 0;
+}
+.fp-handle:hover {
+  cursor: pointer;
+}
+
+/* @end */
+
+/* @group Modes */
+
+/* @group Hover */
+
+.fp-mode-hover .fp-list {
+  z-index: 50;
+}
+.fp-mode-hover .fp-list.fp-level-2,
+.fp-mode-hover .fp-list.fp-level-2 .fp-list {
+  position: absolute;
+}
+.fp-mode-hover .fp-item {
+  position: relative;
+}
+/* This needs to be made RTL friendly */
+.fp-mode-hover.fp-horizontal > .fp-list > .fp-item {
+	float: left;
+}
+
+/* @end */
+
+/* @group Slider */
+
+.fp-mode-slider.fp-wrapper {
+  width: 100%;
+}
+.fp-mode-slider .fp-list {
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  position: absolute;
+  width: 100%;
+}
+.fp-mode-slider .fp-level-1 .fp-list {
+  left: 100%;
+  top: 0;
+}
+
+/* @end */
+
+/* @end */
diff --git a/core/misc/ui/menus/flexipanda/jquery.flexipanda.js b/core/misc/ui/menus/flexipanda/jquery.flexipanda.js
new file mode 100644
index 0000000..96bf027
--- /dev/null
+++ b/core/misc/ui/menus/flexipanda/jquery.flexipanda.js
@@ -0,0 +1,1037 @@
+/*jslint bitwise: true, eqeqeq: true, immed: true, newcap: true, nomen: false,
+ onevar: false, plusplus: false, regexp: true, undef: true, white: true, indent: 2
+ browser: true */
+ 
+/*global jQuery: true debug: true window: true */
+
+/**
+ * FlexiPanda - a jQuery plugin.
+ *
+ * Create robust, elegant dropdown menus.
+ *
+ * Author: Jesse Beach
+ * Author URI: http://qemist.us
+ * Author Twitter: @jessebeach
+ * Author Github: https://github.com/jessebeach
+ */
+
+(function (window, undefined) {
+  if (window.jQuery === undefined) {
+    return null;
+  }
+  // Replace 'pluginName' with the name of your plugin.
+  var plugin = 'flexiPanda',
+  // A private reference to this $plugin object.
+  $plugin,
+  // Local copy of jQuery.
+  $ = window.jQuery,
+  // Local copies of context globals.
+  // Use the correct document accordingly with window argument (sandbox)
+  document = window.document,
+  navigator = window.navigator,
+  location = window.location,
+  // Local copy of jQuery.
+  $ = window.jQuery,
+  // Private variables
+  html = document.documentElement,
+  textDirection = (html.dir) ? html.dir : 'ltr';
+
+  /**
+   * Clear all the timers on an element.
+   */
+  function clearDelay(context) {
+    var context = context || this;
+    var $context = ('jquery' in context) ? context : $(context);
+    var data = $context.data()[plugin];
+    if ('timers' in data) {
+      while (data.timers.timeouts.length > 0) {
+        clearTimeout(data.timers.timeouts.pop());
+      }
+      while (data.timers.intervals.length > 0) {
+        clearInterval(data.timers.intervals.pop());
+      }
+    }
+    $context.trigger('debug');
+  }
+  /**
+   * Create a delay to call a function on an element.
+   */
+  function setDelay(fn, context, options) {
+    // Nothing to do without a function.
+    if (!fn) {
+      return null;
+    }
+    var context = context || this;
+    var $context = ('jquery' in context) ? context : $(context);
+    if ($context.length === 0) {
+      return;
+    }
+    var options = options || {};
+    // 'args' here needs to be made more robust so it isn't assumed that the value
+    // is a single string.
+    // $.proxy works with the signature of (fn, context [, options]) in jQuery 1.7+
+    // but not in 1.4, so I had to make my own function.
+    var proxy = fakeProxy(fn, $context, ('args' in options) ? options.args : null);
+    if ($.isFunction(proxy)) {
+      var delay = ('delay' in options) ? options.delay : 500;
+      var timeout;
+      // Add a timer to the context
+      var data = $context.data();
+      if (!data) {
+        $context.data(plugin, {});
+        data = $context.data();
+      }
+      // Store timeouts and intervals on the object.
+      if (!('timers' in data)) {
+        data.timers = {timeouts: [], intervals: []};
+      }
+      if ('type' in options && options.type === 'interval') {
+        data.timers.intervals.push(setInterval(proxy, delay));
+      } else {
+        data.timers.timeouts.push(setTimeout(proxy, delay));
+      }
+    }
+    $context.trigger('debug');
+  }
+  /**
+   *
+   */
+  function buildClearDelay(event) {
+    clearDelay(this);
+  }
+  /**
+   *
+   */
+  function buildTriggerDelay (event) {
+    event.data = ('data' in event) ? event.data : {};
+    setDelay($.fn.trigger, $(this), {'delay': event.data.delay || undefined, 'args': event.data.args || undefined});
+  }
+  /**
+   * This exists because $.proxy can't be overloaded in jQuery 1.4.
+   */
+  function fakeProxy(fn, context) {
+    var args = Array.prototype.slice.call(arguments, 2);
+    return function () {
+      fn.apply(context, args);
+    }
+  }
+  /**
+   *
+   */
+  function initItems(event) {
+    event.stopImmediatePropagation();
+    // The plugin wrapper.
+    var $wrapper = $(this);
+    var options = $wrapper.data(plugin).options;
+    var rootClass = 'fp-root';
+    var listClass = 'fp-list';
+    var itemClass = 'fp-item';
+    var linkClass = 'fp-link';
+    // Get lists and items.
+    // @TODO, we want to allow arbitrary HTML in item bodies,
+    // so this selection will need to be tighter.
+    var $root = $wrapper.children('.' + rootClass);
+    var $ul = $wrapper.find('ul').not('.' + listClass);
+    var $li = $wrapper.find('li').not('.' + itemClass);
+    // Basic setup
+    $ul
+    .addClass(listClass)
+    .each(function (index, element) {
+      $(this).data('flexiPanda', {
+        processed: false,
+        type: 'list',
+        level: NaN
+      });
+    });
+    // Initialize items and their links.
+    $li
+    .addClass(itemClass)
+    .each(function (index, element) {
+      $(this).data('flexiPanda', {
+        processed: false,
+        type: 'item'
+      });
+    })
+    // Add a class to item links.
+    .children('a')
+    .addClass(linkClass)
+    .end()
+    .trigger('prepare');    
+    // Indicate the level of each menu.
+    markListLevels($root);
+    // Set visibility
+    setLevelVisibility($root, options['hide-levels-after']);
+    // Set positioning
+    setLevelPositioning($root, options['position-levels-after']);
+    // Set orientation.
+    setOrientation.call($wrapper, options['orientation']);
+    // Trigger setup events.
+    $ul
+    // Trigger debugging.
+    .trigger('debug', {enable: options.debug});
+    
+    $li
+    // Establish item data.
+    .trigger('refresh')
+    // Trigger debugging.
+    .trigger('debug', {enable: options.debug});
+  }
+  /**
+   * Clean the interaction classes from the element and its children.
+   */
+  function cleanItem(event) {
+    event.stopImmediatePropagation();
+    $(this)
+    .removeClass('fp-trail fp-active fp-hovered fp-clicked');
+  }
+  /**
+   *
+   */
+  function cleanMenu(event) {
+    $(this)
+    .find('.fp-trail')
+    .trigger('clean');
+  }
+  /**
+   * Handles the hover event of li elements.
+   */
+  function activateItem(event) {
+    if (!event.hoverProcessed) {
+      // liveFired is replaced with delegateTarget in jQuery 1.7
+      var $root = $(event.liveFired);
+      $(this)
+      // Clean out all .fp-trail classes.
+      .closest('.fp-wrapper')
+      .find('.fp-trail')
+      .trigger('clean')
+      .end()
+      .end()
+      // Trace the active trail.
+      .addClass('fp-trail fp-active')
+      .parentsUntil('.fp-wrapper')
+      .filter('.fp-item')
+      .addClass('fp-trail')
+      .end()
+      .end()
+      // Deal with window collisions.
+      .flexiPanda('parentList')
+      .trigger('rebounded');
+    }
+    // Propagation shouldn't be stopped here, but this function
+    // should only run once.
+    event.hoverProcessed = true;
+  }
+  /**
+   * Hangles the click event of li elements.
+   */
+  function itemClick(event) {
+    event.preventDefault();
+    event.stopPropagation();
+    $(this)
+    .trigger('pathSelected')
+    .addClass('fp-trail fp-clicked')
+    .closest('ul')
+    .trigger('debug');
+  }
+  /**
+   * Adds an fp-level class to each list based on its depth in the menu.
+   */
+  function markListLevels($lists, level) {
+    level = level || 1;
+    $lists
+    .addClass('fp-level-' + level)
+    .each(function (index, element) {
+      $(this).data().flexiPanda.level = level;
+    });
+    $lists = $lists.children('li').children('ul');
+    if ($lists.length > 0) {
+      markListLevels($lists, (level + 1));
+    }
+  }
+  /**
+   *
+   */
+  function setLevelVisibility($lists, visibleAfter) {
+    var level;
+    $lists
+    .each(function (index, element) {
+      var $this = $(this);
+      level = $(this).data().flexiPanda.level;
+      if (level > visibleAfter) {
+        $this.addClass('fp-dormant');
+      }
+      else {
+        $this.addClass('fp-visible');
+      }
+    });
+    $lists = $lists.children('li').children('ul');
+    if ($lists.length > 0) {
+      setLevelVisibility($lists, visibleAfter);
+    }
+  }
+  /**
+   *
+   */
+  function setLevelPositioning($lists, positionedAfter) {
+    var level;
+    $lists
+    .each(function (index, element) {
+      var $this = $(this);
+      level = $(this).data().flexiPanda.level;
+      if (level > positionedAfter) {
+        $this.addClass('fp-pegged');
+      }
+      else {
+        $this.addClass('fp-unpegged');
+      }
+    });
+    $lists = $lists.children('li').children('ul');
+    if ($lists.length > 0) {
+      setLevelPositioning($lists, positionedAfter);
+    }
+  }
+  /**
+   * 
+   */
+  function setOrientation(orientation) {
+    var $this = $(this);
+    switch (orientation) {
+    case 'horizontal':
+      $this.addClass('fp-horizontal');
+      break;
+    case 'vertical':
+      $this.addClass('fp-vertical');
+      break;
+    default:
+      $this.addClass('fp-horizontal');
+      break;
+    }
+  }
+  /**
+   * Determines if the dimenions are outside the bounds of the viewport.
+   */
+  function checkBounds(dimensions) {
+    return {
+      left: (dimensions.left === undefined) ? undefined : (dimensions.left >= 0),
+      top: (dimensions.top === undefined) ? undefined : (dimensions.top >= 0),
+      right: (dimensions.right === undefined) ? undefined : (dimensions.right >= 0),
+      bottom: (dimensions.bottom === undefined) ? undefined : (dimensions.bottom >= 0)
+    };
+  }
+  /**
+   *
+   */
+  function checkDataFreshness(data) {
+    // If the item hasn't been processed, just return.
+    if (data.processed === false || data.processed === undefined) {
+      return null;
+    }
+    data.dimensions = data.dimensions || {};
+    // If the item knows nothing about the client yet,
+    // then the data is stale.
+    if (data.dimensions.client === undefined) {
+      data.processed = false;
+      return null;
+    }
+    // Get the current client dimensions.
+    var client = {
+      left: document.documentElement.clientLeft,
+      top: document.documentElement.clientTop,
+      height: document.documentElement.clientHeight,
+      width: document.documentElement.clientWidth
+    }, 
+    edge = '';
+    for (edge in client) {
+      if (client.hasOwnProperty(edge)) {
+        if (client[edge] !== data.dimensions.client[edge]) {
+          data.processed = false;
+          return null;
+        }
+      }
+    }
+  }
+  /**
+   * Moves elements around the page based on a vector object.
+   *
+   * param vectors {object}
+   */
+  function move(vectors) {
+    var $this = $(this),
+    elem = $this.get(0),
+    offset = $this.offset(),
+    coords = {};
+    if (vectors.right && textDirection === 'ltr') {
+      coords.left = (offset.left + vectors.right);
+    }
+    if (vectors.left && textDirection === 'rtl') {
+      coords.left = (offset.left - vectors.left);
+    }
+    if (vectors.bottom) {
+      coords.top = (offset.top + vectors.bottom);
+    }
+    if (vectors.top) {
+      coords.top = (offset.top - vectors.top);
+    }
+    // Move the item.
+    $this.offset(coords);
+  }
+  /**
+   * Shifts the item lists with margins.
+   */
+  function shiftPosition(data, options) {
+    var $this = $(this),
+    vectors = {top: {dir: 'top', sign: ''}, bottom: {dir: 'top', sign: '-'}},
+    vector = '',
+    tolerance = options.tolerance,
+    buffer = options.buffer,
+    delta = 0,
+    occlusionFix = {},
+    fixes = 0;
+    // LRT and RTL languages are dealt with separately.
+    if (textDirection === 'rtl') {
+      vectors.left = {dir: 'left', sign: ''};
+    }
+    else {
+      vectors.right = {dir: 'left', sign: '-'};
+    }
+    var dimensions = data.dimensions.item,
+    parentListDimensions = data.dimensions.parentList;
+    for (vector in vectors) {
+      if (vectors.hasOwnProperty(vector)) {
+        var index = 'margin-' + vectors[vector].dir;
+        // If the list is closer to the viewport than tolerance, shift it with margins
+        // to the tolerance value.
+        if (dimensions[vector] < tolerance) {
+          delta = tolerance - dimensions[vector];
+          var obj = {};
+          obj[index] = vectors[vector].sign + delta + 'px';
+          $this.css(obj);
+        }
+        // If the list occludes its parent lists, shift it with margins.
+        if (parentListDimensions) {
+          var diff = Math.abs((dimensions[vector] + delta) - parentListDimensions[vector]);
+          if (diff < tolerance) {
+            delta = buffer - diff;
+            occlusionFix[index] = vectors[vector].sign + buffer + 'px';
+            fixes += 1;
+            if (fixes > 1) {
+              $this.css(occlusionFix);
+            }
+          }
+        }
+      }
+    }
+  }
+  /**
+   * Responds to the rebounded event.
+   */
+  function reposition(event) {
+    event.stopPropagation();
+    var $this = $(this);
+    // Remove any margins from position shifting.
+    $this.css({margin: 0});    
+    var data = $this.trigger('refresh').data().flexiPanda,
+    dimensions = data.dimensions,
+    // Check if the item falls within the bounds of the viewport within the
+    // configured tolerance.
+    bounds = checkBounds(dimensions.item),    
+    // idealBounds is the placement of the item if the viewport had no limits.
+    idealBounds = checkBounds(dimensions.ideal),
+    edge = '',
+    vectors = {};
+    // Move the item if it is out of bounds
+    for (edge in bounds) {
+      if (bounds.hasOwnProperty(edge)) {
+        // If the idealBound is true and the ideal bound is closer to the client
+        // edge than the current item edge, move it the difference of the distance
+        // between the two positions.
+        if (idealBounds[edge] === true && (dimensions.ideal[edge] > 0) && (dimensions.ideal[edge] < dimensions.item[edge])) {
+          vectors[edge] = dimensions.item[edge] - dimensions.ideal[edge];
+        }
+        // If the idealBound is false and the current item edge is farther from the
+        // client edge than the tolerance, reposition it.
+        if (idealBounds[edge] === false && (dimensions.item[edge] > 0)) {
+          vectors[edge] = dimensions.item[edge];
+        }
+        // If the item is outside the edge of the screen, reposition it.
+        if (bounds[edge] === false) {
+          vectors[edge] = dimensions.item[edge];
+        }
+        idealBounds[edge] = bounds[edge] = true;
+      }
+    }
+    // Move the item. 
+    // move() will deal with conflicting vectors
+    if (!$.isEmptyObject(vectors)) {
+      move.call(this, vectors);
+      data = $this.trigger({type: 'refresh', cache: false}).data().flexiPanda;
+    }
+    // Shift the lists by adjusting margins to correct lists against the edge 
+    // of the screen and lists occluding other lists.
+    shiftPosition.call(this, data, event.data.edge);
+    
+    // Trigger refresh on the child lists. Parent lists have to be repositioned
+    // before child lists.
+    $this.find('.fp-level-' + (data.level + 1)).trigger('rebounded');
+  }
+  /**
+   *
+   */
+  function insertItemHandles(event) {
+    event.stopImmediatePropagation();
+    var options = event.data.options;
+    var $item = $(this);
+    var $link = $item.children('.fp-link');
+    var $box = $link
+    .wrap(
+      $('<div>', {
+        'class': 'fp-box'
+      })
+    )
+    .parent();
+    var handleClass = 'fp-handle';
+    if ($item.children('.fp-list').length > 0 || $item.hasClass('fp-back')) {
+      // If handles are disabled, make the link the click handler.
+      if (!options['menu-handles']['show']) {
+        $link.addClass(handle);
+        return;
+      }
+      // The placement of the handles requires a positing context that can
+      // be set to relative. This will not work on the .fp-items.
+      $box
+      .prepend(
+        $('<span>', {
+          'class': handleClass,
+          text: options['menu-handles']['content']
+        })
+      );
+    }
+  }
+  /**
+   * Build the Slider menu when it is instantiated.
+   */
+  function sliderSetup(event) {
+    var $this = $(this);
+    // Mark up the lists and items.
+    $this
+    .trigger('listChange')
+    // Add slider controls.
+    .find('.fp-list')
+    .not('.fp-root')
+    .each(function (index, element) {
+      // Add a back button.
+      var label = '';
+      var $parentItem = $(this).flexiPanda('parentItem');
+      if ($parentItem.length > 0) {
+        label = $parentItem.children('.fp-box').find('.fp-link').text();
+      }
+      $(this)
+      .prepend(
+        $('<li>', {
+          html: $('<a>', {
+            text: (label.length > 0) ? label : Drupal.t('back')
+          }),
+          'class': 'fp-back'
+        })
+      ) 
+    })
+    .end()
+    .end()
+    // Mark up the back buttons.
+    .trigger('listChange')
+    .trigger('reflowed');
+    
+  }
+  /**
+   * Bring the Slider menu back to the root and clean active items.
+   */
+  function sliderReset(event) {
+    var $this = $(this);
+    // Clean active items.
+    $this
+    .find('.fp-root')
+    .animate({
+      'left': 0
+    }, 250)
+    .find('.fp-item')
+    .trigger('clean')
+    .end()
+    .end()
+    .trigger('reflowed');
+    
+  }
+  /**
+   * Since the Slider wrapper is set to overflow hidden, we need to manage
+   * its height or risk hiding items in the menu list.
+   *
+   * Reflow is called when items are added to the list, when the menu slides,
+   * or when the menu is reset.
+   */
+  function sliderReflow(event) {
+    var $this = $(this);
+    var $activeList = $this.find('.fp-item.fp-active > .fp-list');
+    var height = 'auto';
+    if ($activeList.length > 0) {
+      height = $activeList.outerHeight();
+    }
+    else {
+      var h = 0;
+      $this.find('.fp-root').children('.fp-item').each(function(index, element) {
+        h += $(this).outerHeight();
+      });
+      height = h || 'auto';
+    }
+    // Set the height.
+    $this.animate({
+      height: height
+    }, 100);
+  }
+  /**
+   * Move the Slider menu left or right.
+   */
+  function slide(level, sign) {
+    // Move the item and list left the width of the wrapper.
+    this
+    .animate({
+      'left': sign + (level * 100) + '%'
+    }, 250);
+  }
+  /**
+   *
+   */
+  function slideForward(event) {
+    event.preventDefault();
+    // Keep the menu from multiple-sliding.
+    event.stopPropagation();
+    var $this = $(this);
+    var $wrapper = $this.flexiPanda('wrapper');
+    var $root = $this.flexiPanda('root');
+    var $item = $this.closest('.fp-item');
+    var level = $this.closest('.fp-list').data()[plugin].level;
+    var $list = $item.children('.fp-list');
+    var sign = '-';
+    var unit = '%';
+    // Return is the item has no sub-menus.
+    if ($list.length === 0) {
+      return;
+    }
+    // Slide the menu
+    slide.call($root, level, sign);
+    // Make the list item element active.
+    $item.trigger('activate');
+    // Reflow to get the height calculation.
+    $wrapper.trigger('reflowed');
+  }
+  /**
+   *
+   */
+  function slideBack(event) {
+    event.preventDefault();
+    // Keep the menu from multiple-sliding.
+    event.stopImmediatePropagation();
+    // Navigate link.
+    var $this = $(this);
+    var $wrapper = $this.flexiPanda('wrapper');
+    var $root = $this.flexiPanda('root');
+    var $list = $this.closest('.fp-list');
+    var $item = $this.flexiPanda('parentItem');
+    // The level determines how far to move the menu i.e. level * 100.
+    var level = Number($list.data()[plugin].level) - 2;
+    var sign = (level === 0) ? '' : '-';
+    
+    // Slide the menu
+    slide.call($root, level, sign);
+    // Clean the active item. A little hinky, but it works.
+    var event = {
+      data: {}
+    };
+    // Clean the trail after a delay.
+    event.data = {
+      delay: 150,
+      args: 'clean'
+    };
+    buildTriggerDelay.call($item, event);
+    // The parent item of this item is now the active item.
+    event.data = {
+      delay: 200,
+      args: 'activate'
+    };
+    buildTriggerDelay.call($item.flexiPanda('parentItem'), event);
+    // Reflow to get the height calculation.
+    event.data = {
+      delay: 250,
+      args: 'reflowed'
+    };
+    buildTriggerDelay.call($wrapper, event);
+  }
+  /**
+   * Saves the dimensions of each item in its data() object.
+   */
+  function setItemData(event) {
+    event.stopPropagation();
+    var $this = $(this),
+    cache = (event.cache !== undefined) ? event.cache : true,
+    data = $this.data().flexiPanda;
+    checkDataFreshness.call(this, data);
+    // Only process the item's data if cache is false (meaning the
+    // cache is intentionally busted) or if the item has not been
+    // processed yet. This function gets called a lot and it 
+    // interacts heavily with the DOM, so it should be run without cause.
+    if (!cache || !data.processed) {
+      data.classes = this.classList;
+      var $parentItem = $this.flexiPanda('parentItem'),
+      $parentList = $this.flexiPanda('parentList'),
+      offset = NaN,
+      width = NaN,
+      height = NaN,
+      client = {
+        left: document.documentElement.clientLeft,
+        top: document.documentElement.clientTop,
+        height: document.documentElement.clientHeight,
+        width: document.documentElement.clientWidth
+      };
+      data.parentItem = $parentItem;
+      data.parentList = $parentList;
+      data.dimensions = {};
+      data.dimensions.client = client;
+      // Get the dimensions of the parent list
+      if ($parentList.length > 0) {
+        offset = $parentList.offset();
+        width = $parentList.width();
+        height = $parentList.height();
+        data.dimensions.parentList = {
+          width: width,
+          height: height,
+          left: offset.left,
+          right: client.width - (offset.left + width),
+          top: offset.top,
+          bottom: client.height - (offset.top + height)
+        };
+      }
+       // Get the dimensions of the parent item
+      if ($parentItem.length > 0) {
+        offset = $parentItem.offset();
+        width = $parentItem.width();
+        height = $parentItem.height();
+        data.dimensions.parentItem = {
+          width: width,
+          height: height,
+          top: offset.top,
+          bottom: client.height - (offset.top + height)
+        };
+      }
+      offset = $this.offset();
+      height = $this.outerHeight(false);
+      width = $this.outerWidth(false);
+      // These dimensions are calculated as distance from the respective
+      // edge of the viewport, not as distance from the left/top origin.
+      // This allows us to know if an item is out of bounds if the
+      // distance is negative.
+      data.dimensions.item = {
+        width: width,
+        height: height,
+        left: offset.left,
+        top: offset.top,
+        right: (client.width - (offset.left + width)),
+        bottom: (client.height - (offset.top + height))
+      };
+      // The placement of the element if the viewport had no limits.
+      data.dimensions.ideal = {};
+      if (data.dimensions.parentItem) {
+        data.dimensions.ideal.top = data.dimensions.parentItem.top;
+        data.dimensions.ideal.bottom = client.height - (data.dimensions.ideal.top + data.dimensions.item.height);
+      }
+      if (data.dimensions.parentList) {
+        /* LTR text */
+        if (textDirection === 'ltr' || textDirection === 'undefined') {
+          data.dimensions.ideal.left = data.dimensions.parentList.left + data.dimensions.parentList.width;
+          data.dimensions.ideal.right = client.width - (data.dimensions.ideal.left + data.dimensions.item.width);
+        }
+        /* RTL text */
+        if (textDirection === 'rtl') {
+          data.dimensions.ideal.left = data.dimensions.parentList.left - data.dimensions.parentList.width;
+          data.dimensions.ideal.right = client.width - (data.dimensions.ideal.left - data.dimensions.item.width);
+        }
+      }
+      // Mark this item as processed.
+      data.processed = true;
+    }
+  }
+  /**
+   * Returns a <ul> list from a javascript object.
+   */
+  function listMaker(data) {
+    var $list = $('<div>');
+    for (var datum in data) {
+      if (data.hasOwnProperty(datum)) {
+        var $item = $('<div>');
+        $item.append($('<span>', {
+          text: datum + ': '
+        }));
+         // Deal with objects.
+        if (typeof(data[datum]) === 'object') {
+          // jQuery objects are large and will stall the browse
+          // if we try to print them. Just state that this is
+          // a jQuery object.
+          if (data[datum].jquery) {
+            $item.append($('<b>', {
+              text: '[jQuery] jQuery object'
+            }));
+          }
+          // Otherwise recurse the function.
+          else {
+            $item.append(listMaker(data[datum]));
+          }
+        }
+        else {
+          $item.append($('<b>', {
+            text: '[' + typeof(data[datum]) + '] ' + data[datum]
+          }));
+        }
+        $item.appendTo($list);
+      }
+    }
+    return ($list.children().length > 0) ? $list : $('<span>', {
+      text: 'null'
+    });
+  }
+  /**
+   * Returns a renderable list of item data for debugging.
+   */
+  function renderItemData() {
+    var $this = $(this),
+    data = $this.data().flexiPanda,
+    $list = listMaker(data).addClass('fp-data');
+    return ($list.children().length > 0) ? $list : $();
+  }
+  /**
+   * Handles window resizes. This should work the same for all menu modes.
+   */
+  function handleResize(event) {
+    $('.fp-wrapper')
+    .trigger('reflowed');    
+  }
+  // private function for debugging
+  function getDebugger($element) {
+    var $debugger = $element.children('.fp-debug').detach();
+    // Make a new debugger or detach the existing one.
+    return (!$debugger.length > 0) ? $('<div>').addClass('fp-debug') : $debugger;
+  }
+  /**
+   * Appends a debugger to elements listening to debug events.
+   */
+  function debug(event) {
+    event.stopPropagation();
+    var $this = $(this);
+    
+    var $debugger = getDebugger($this),
+        items = $.proxy(renderItemData, this)();
+    
+    if (items.length > 0) {
+      $debugger
+      .html(items)
+      .css({
+        left: 50,
+        position: 'absolute'
+      })
+      .appendTo($this);
+    }
+  }
+  /**
+   * Public methods of the flexiPanda plugin.
+   */
+  var methods = {
+    init : function (options) {
+      // Add the dir attribute to the HTML element if it does not exist.
+      // This is part of RTL language support.
+      if ($('html').attr('dir') === undefined) {
+        $('html').attr('dir', textDirection);
+      }
+      // Build main options before element iteration.
+      options = $.extend({}, $.fn.flexiPanda.defaults, options);
+      // Handle screen resizes
+      // This could be made much more efficient in jQuery 1.6+ with Callbacks.
+      $(window).bind('resize.flexiPanda', handleResize);
+      // Iterate over matched elements.
+      return this.each(function () {
+        var $root = $(this).addClass('fp-root');
+        // Wrap the list in a div to provide a positioning context.
+        var $wrapper = $root.wrap($('<div>')
+          .css({
+            height: '100%',
+            position: 'relative'
+          })
+          .data(plugin, {
+            options: options
+          })
+          .addClass('fp-wrapper')
+        ).parent();
+        // Bind event handlers.
+        $wrapper
+        .delegate('.fp-list, .fp-item', 'debug.flexiPanda', {}, (options.debug) ? debug : function () {return false; })
+        .delegate('.fp-item', 'prepare.flexiPanda', {options: options}, insertItemHandles)
+        // Called when items are added or removed.
+        .bind('listChange.flexiPanda', initItems);
+        // Set up the behavior mode
+        switch (options.mode) {
+        case 'click' :
+        // Click mode
+          $wrapper
+          .delegate('.fp-item', 'click.flexiPanda.clickMode', itemClick)
+          .delegate('.fp-list, .fp-item', 'refresh.flexiPanda', setItemData)
+          .delegate('.fp-pegged', 'rebounded.flexiPanda', {edge: options.edge}, reposition)
+          .delegate('.fp-item', 'clean.flexiPanda', cleanItem)
+          .delegate('.fp-item', 'activate.flexiPanda.hoverMode', activateItem)
+          .addClass('fp-mode-click');
+          break;
+        case 'hover' :
+          // Hover mode
+          $wrapper
+          .delegate('.fp-root', 'mouseenter.flexiPanda.hoverMode', buildClearDelay)
+          .delegate('.fp-root', 'mouseleave.flexiPanda.hoverMode', {delay: options.delays.menu, args: 'exit'}, buildTriggerDelay)
+          .delegate('.fp-root', 'exit.flexiPanda', cleanMenu)
+          .delegate('.fp-list, .fp-item', 'refresh.flexiPanda', setItemData)
+          .delegate('.fp-pegged', 'rebounded.flexiPanda', {edge: options.edge}, reposition)
+          .delegate('.fp-item', 'clean.flexiPanda', cleanItem)
+          .delegate('.fp-item', 'mouseenter.flexiPanda.hoverMode', activateItem)
+          .addClass('fp-mode-hover');					
+          $ul
+          // Move sub menus that might be positioned outside the viewport.
+          .trigger('rebounded');
+          break;
+        case 'slider' :
+          // Mobile slider mode
+          $wrapper
+          .bind('reflowed.flexiPanda.sliderMode', sliderReflow)
+          .bind('setup.flexiPanda.sliderMode', sliderSetup)
+          .bind('reset.flexiPanda.sliderMode', sliderReset)
+          .delegate('.fp-handle:not(.fp-back .fp-handle)', 'click.flexiPanda.sliderMode', slideForward)
+          .delegate('.fp-item', 'clean.flexiPanda', cleanItem)
+          .delegate('.fp-item', 'activate.flexiPanda.hoverMode', activateItem)
+          .delegate('.fp-back', 'click.flexiPanda.sliderMode', slideBack)
+          .addClass('fp-mode-slider');
+          break;
+        default:
+        }
+        // Set up the plugin.
+        $wrapper
+        .trigger('setup');
+      });
+    },
+    clean: function () {
+      return this.each(function () {
+        // Clean returns the menu to its resting state.
+        $(this).trigger('reset');
+      });
+    },
+    // This function doesn't chain correctly yet.
+    destroy : function () {
+      var $wrapper = this;
+      var $menu;
+      // Find the wrapper
+      if (!$wrapper.hasClass('fp-wrapper')) {
+        $wrapper = this.closest('.fp-wrapper');
+      }
+      $menu = $wrapper.children('.fp-root');
+      $debug = $wrapper.find('.fp-debug');
+      // Remove event handlers.
+      $wrapper.undelegate('.flexiPanda').find('*').each(function () {
+        var $this = $(this);
+        // Remove fp- namespaced classes.
+        $this[0].className = $this[0].className.replace(/\bfp.*?\b/g, '');
+      });
+      // Remove debug elements.
+      $debug.remove();
+      // Unwrap the element
+      $menu.unwrap();
+      // Return the menu item for chaining.
+      return this.pushStack($menu.get());
+    },
+    // Custom traversal functions
+    parentItem : function () {
+      var data = this.data().flexiPanda,
+      parent = $();
+      if (data.type === 'item') {
+        parent = this.closest('.fp-list').closest('.fp-item');
+        return this.pushStack(parent.get());
+      }
+      if (data.type === 'list') {
+        parent = this.closest('.fp-item');
+        return this.pushStack(parent.get());
+      }
+      return this.pushStack(parent.get());
+    },
+    parentList : function () {
+      var data = this.data().flexiPanda,
+      parent = $();
+      if (data.type === 'item') {
+        parent = this.closest('.fp-list').closest('.fp-item').closest('.fp-list');
+        return this.pushStack(parent.get());
+      }
+      if (data.type === 'list') {
+        parent = this.closest('.fp-item').closest('.fp-list');
+        return this.pushStack(parent.get());
+      }
+      return this.pushStack(parent.get());
+    },
+    childLists: function () {
+      var children = $();
+      // Just return if this is zero length.
+      if (this.length === 0) {
+        return this.pushStack(children.get());
+      }
+      var data = this.data().flexiPanda;
+      if (data.type === 'item') {
+        children = this.children('.fp-list');
+        return this.pushStack(children.get());
+      }
+      if (data.type === 'list') {
+        children = this.children('.fp-item').children('.fp-list');
+        return this.pushStack(children.get());
+      }
+      // Just return a null set if none of the cases match.
+      return this.pushStack(children.get());
+      
+    },
+    root : function () {
+      return this.pushStack(this.closest('.fp-root').get());
+    },
+    wrapper : function () {
+      return this.pushStack(this.closest('.fp-wrapper').get());
+    }
+  };
+
+  // Add the plugin to the jQuery fn object.
+  $.fn.flexiPanda = function (method) {
+    // Method calling logic
+    if (methods[method]) {
+      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+    } else if (typeof method === 'object' || ! method) {
+      return methods.init.apply(this, arguments);
+    } else {
+      $.error('Method ' +  method + ' does not exist on jQuery.flexiPanda');
+    }
+  };
+    
+  // FlexiPanda plugin defaults.
+  $.fn.flexiPanda.defaults = {
+    dev: true,
+    delays: {
+      menu: 1000,
+      item: 200
+    },
+    mode: 'hover',
+    'hide-levels-after': 1,
+    'position-levels-after': 2,
+    orientation: 'horizontal',
+    debug: true,
+    edge: {
+      tolerance: 10,
+      buffer: 14
+    },
+    'menu-handles': {
+      show: true,
+      content: ''
+    }
+  };
+}(window));
\ No newline at end of file
diff --git a/core/modules/shortcut/shortcut.base.css b/core/modules/shortcut/shortcut.base.css
index 90a1046..91e565c 100644
--- a/core/modules/shortcut/shortcut.base.css
+++ b/core/modules/shortcut/shortcut.base.css
@@ -10,12 +10,6 @@
 #edit-shortcuts {
   float: right; /* LTR */
 }
-#shortcut-toolbar ul {
-  float: left; /* LTR */
-}
-#shortcut-toolbar .icon {
-  float: left; /* LTR */
-}
 
 /**
  * Add/remove links.
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 9bbb12a..96c2c6b 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -716,10 +716,10 @@ function shortcut_preprocess_page(&$variables) {
  * Implements hook_page_alter().
  */
 function shortcut_page_alter(&$page) {
-  if (isset($page['page_top']['toolbar'])) {
+  if (isset($page['page_bottom']['toolbar'])) {
     // If the toolbar is available, add a pre-render function to display the
     // current shortcuts in the toolbar drawer.
-    $page['page_top']['toolbar']['#pre_render'][] = 'shortcut_toolbar_pre_render';
+    $page['page_bottom']['toolbar']['#pre_render'][] = 'shortcut_toolbar_pre_render';
   }
 }
 
diff --git a/core/modules/shortcut/shortcut.theme.css b/core/modules/shortcut/shortcut.theme.css
index 9e2dc69..930f466 100644
--- a/core/modules/shortcut/shortcut.theme.css
+++ b/core/modules/shortcut/shortcut.theme.css
@@ -5,45 +5,6 @@
  */
 
 /**
- * Toolbar.
- */
-.toolbar #edit-shortcuts {
-  line-height: 24px;
-  padding: 5px 10px;
-}
-#edit-shortcuts:focus,
-#edit-shortcuts:hover,
-#edit-shortcuts.active {
-  text-decoration: underline;
-}
-#shortcut-toolbar ul {
-  line-height: 24px;
-  margin-left: 5px; /* LTR */
-  padding: 5px 0;
-}
-#shortcut-toolbar a {
-  border-radius: 5px;
-  margin-right: 5px; /* LTR */
-  padding: 0 5px;
-}
-#shortcut-toolbar a:focus,
-#shortcut-toolbar a:hover,
-#shortcut-toolbar a.active:focus {
-  background: #555;
-}
-#shortcut-toolbar a.active:hover,
-#shortcut-toolbar a.active {
-  background-color: #000;
-}
-#shortcut-toolbar .icon {
-  background-color: #444;
-  border-radius: 5px;
-  height: 30px;
-  margin-right: 5px; /* LTR */
-  width: 30px;
-}
-
-/**
  * Add/remove links.
  */
 .add-or-remove-shortcuts .icon {
@@ -65,15 +26,3 @@
 .remove-shortcut a:hover .icon {
   background-position: -12px -12px; /* LTR */
 }
-.add-or-remove-shortcuts .text {
-  padding: 0 6px 0 10px; /* LTR */
-}
-.add-or-remove-shortcuts a:focus .text,
-.add-or-remove-shortcuts a:hover .text {
-  background-color: #5f605b;
-  border-radius: 0 5px 5px 0; /* LTR */
-  color: #fff;
-  cursor: pointer;
-  font-size: 10px;
-  line-height: 12px;
-}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ad4c5dd..11e3769 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1893,6 +1893,22 @@ function system_library_info() {
     ),
   );
 
+  // Flexible menus.
+  $libraries['jquery.flexipanda'] = array(
+    'title' => 'FlexiPanda responsive menus',
+    'website' => 'http://jessebeach.github.com/flexiPanda/',
+    'version' => '1.0.0', // Shipped with jQuery UI.
+    'js' => array(
+      'core/misc/ui/menus/flexipanda/jquery.flexipanda.js' => array(),
+    ),
+    'css' => array(
+      'core/misc/ui/menus/flexipanda/css/jquery.flexipanda.css' => array(),
+    ),
+    'dependencies' => array(
+      array('system', 'jquery'),
+    ),
+  );
+
   $libraries['drupal.tableselect'] = array(
     'title' => 'Tableselect',
     'version' => VERSION,
diff --git a/core/modules/toolbar/css/toolbar.base-rtl.css b/core/modules/toolbar/css/toolbar.base-rtl.css
new file mode 100644
index 0000000..253b758
--- /dev/null
+++ b/core/modules/toolbar/css/toolbar.base-rtl.css
@@ -0,0 +1,26 @@
+
+#toolbar,
+#toolbar * {
+  text-align: right;
+}
+#toolbar ul li {
+  float: right;
+}
+#toolbar ul li a {
+  display: inline-block;
+  float: none;
+  zoom: 1;
+}
+#toolbar-user {
+  float: left;
+}
+#toolbar #toolbar-user li {
+  float: none;
+  display: inline;
+}
+#toolbar-menu {
+  float: none;
+}
+#toolbar-home {
+  float: right;
+}
diff --git a/core/modules/toolbar/css/toolbar.base.css b/core/modules/toolbar/css/toolbar.base.css
new file mode 100644
index 0000000..5e4ccde
--- /dev/null
+++ b/core/modules/toolbar/css/toolbar.base.css
@@ -0,0 +1,88 @@
+/**
+ * @file toolbar.admin.css
+ *
+ *
+ * Aggressive resets so we can achieve a consistent look in hostile CSS
+ * environments.
+ */
+body.toolbar {
+  width: 100%;
+}
+#toolbar,
+#toolbar * {
+  border: 0;
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  font-size: 100%;
+  line-height: 1;
+  list-style: none;
+  margin: 0;
+  outline: 0;
+  padding: 0;
+  text-align: left; /* LTR */
+  vertical-align: baseline;
+}
+
+/**
+ * Administration menu.
+ */
+#toolbar .toolbar-bar {
+  left: 0;
+  min-height: 2.2em;
+  position: absolute;
+  right: 0;
+  top: 0;
+  z-index: 600;
+}
+#toolbar .toolbar-bar li {
+  float: left; /* LTR */
+}
+#toolbar .toolbar-bar li a {
+  display: inline-block;
+  line-height: 2.1818em; /* ~24px */
+}
+#toolbar-user {
+  float: right; /* LTR */
+}
+#toolbar-home {
+  float: left; /* LTR */
+}
+/**
+ * Toolbar tray. 
+ */
+#toolbar .toolbar-tray {
+  bottom: 0;
+  left: 0; /* LTR */
+  position: absolute;
+  top: 0;
+  z-index: 600;
+}
+#toolbar .toolbar-tray > .lining {
+  max-height: 100%;
+  overflow: scroll;
+}
+#toolbar .toolbar-tray li a {
+  display: block;
+}
+/* This style seems to belong neither in toolbar nor in shortcut. */
+#toolbar .toolbar-tray #shortcut-toolbar + a {
+  margin-top: 0.3333em;
+}
+
+/**
+ * Wide screens.
+ */
+@media screen and (min-width: 48em) {
+  body.toolbar {
+    -moz-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    padding-top: 2.2em;
+    width: auto;
+  }
+  #toolbar .toolbar-bar,
+  #toolbar .toolbar-tray {
+    position: fixed;
+  }
+}
diff --git a/core/modules/toolbar/css/toolbar.theme-rtl.css b/core/modules/toolbar/css/toolbar.theme-rtl.css
new file mode 100644
index 0000000..bed0a07
--- /dev/null
+++ b/core/modules/toolbar/css/toolbar.theme-rtl.css
@@ -0,0 +1,12 @@
+#toolbar .toolbar-bar {
+  padding: 0.3333em 20px 0.3333em 50px; /* LTR */
+}
+#toolbar .toolbar-bar .toggle-drawer {
+  left: 20px;
+  right: auto;
+}
+
+#toolbar .toolbar-bar .menu li + li {
+  margin-left: auto;
+  margin-right: 1em;
+}
\ No newline at end of file
diff --git a/core/modules/toolbar/css/toolbar.theme.css b/core/modules/toolbar/css/toolbar.theme.css
new file mode 100644
index 0000000..574459d
--- /dev/null
+++ b/core/modules/toolbar/css/toolbar.theme.css
@@ -0,0 +1,210 @@
+/**
+ * @file toolbar.theme.css
+ *
+ *
+ * We use a keyword for the toolbar font size to make it display consistently
+ * across different themes, while still allowing browsers to resize the text.
+ */
+#toolbar {
+  font-family: "Lucida Grande", Verdana, sans-serif;
+  font-size: small;
+  font-style: normal;
+}
+#toolbar a {
+  font-size: 0.846em;
+  text-decoration: none;
+}
+/**
+ * Toolbar bar.
+ */
+#toolbar .toolbar-bar {
+  background-color: #292929;
+  background-image: -moz-linear-gradient(rgba(235, 235, 235, 0.2), transparent);
+  background-image: -o-linear-gradient(rgba(235, 235, 235, 0.2), transparent);
+  background-image: -webkit-linear-gradient(rgba(235, 235, 235, 0.2), transparent);
+  background-image: linear-gradient(rgba(235, 235, 235, 0.2), transparent);
+  border-bottom: 1px solid black;
+  color: #cccccc;
+  line-height: 20px;
+  padding: 0.3333em 20px 0.3333em 50px; /* LTR */
+}
+#toolbar .toolbar-bar .menu li + li {
+  margin-left: 1em; /* LTR */
+}
+#toolbar .toolbar-bar a {
+  color: #ffffff;
+  text-shadow: #585858 0 1px 0;
+}
+#toolbar .toolbar-bar .button {
+  ackground-attachment: scroll;
+  background-color: transparent;
+  background-image: url("../images/toolbar.png");
+  background-repeat: no-repeat;
+  border: 1px solid #333;
+  border-radius: 3px;
+  box-shadow: 1px 1px 1px 0 #888 inset;
+  display: inline-block;
+  cursor: pointer;
+  height: 24px;
+  overflow: hidden;
+  text-indent: -9999px;
+  width: 30px;
+}
+#toolbar .toolbar-bar .home-link {
+  background-position: 9px -19px;
+}
+#toolbar .toolbar-bar .toggle-drawer {
+  background-color: #666;
+  background-position: -1px -2px;
+  border-bottom: 0 none;
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+  bottom: 0;
+  position: absolute;
+  right: 20px;
+  width: 25px;
+}
+#toolbar .toolbar-bar .toggle-drawer:focus,
+#toolbar .toolbar-bar .toggle-drawer:hover {
+  background-position:  -51px -2px;
+}
+#toolbar .toolbar-bar .toggle-drawer.active {
+  background-position:  -26px -2px;
+}
+#toolbar .toolbar-bar .toggle-drawer.active:focus,
+#toolbar .toolbar-bar .toggle-drawer.active:hover {
+  background-position:  -76px -2px;
+}
+
+#toolbar .toolbar-bar .toggle-tray {
+  background-position: -13px -19px;
+  left: 10px;
+  position: absolute;
+};
+
+#toolbar .toolbar-bar li a {
+  padding: 0 10px;
+  -moz-border-radius: 10px;
+  border-radius: 10px;
+}
+/**
+ * Toolbar tray.
+ */
+#toolbar .toolbar-tray {
+  background-color: white;
+  border-right: 1px solid black;
+}
+#toolbar .toolbar-tray > .lining {
+  padding: 1em 0.75em;
+}
+#toolbar .toolbar-tray > * + * {
+  margin-top: 1em;
+}
+#toolbar .toolbar-tray .filter-search {
+  border: 1px solid #ccc;
+  border-radius: 3px;
+  margin: 10px 0 10px 10px;
+}
+#toolbar .toolbar-tray ul li {
+  border-bottom: 1px solid #ccc;
+}
+#toolbar .toolbar-tray ul
+#toolbar .toolbar-tray ul li.last {
+  border-bottom: 0 none;
+}
+#toolbar .toolbar-tray li a {
+  color: #000;
+  padding: 10px 0;
+}
+
+#toolbar .toolbar-tray .filter {
+  padding: 0.0167em;
+  width: 100%;
+}
+
+#toolbar .toolbar-tray span.close {
+  margin: 3px 4px 0 0;
+}
+#toolbar .toolbar-tray .filter-search a {
+  background-image: url("../images/toolbar.png");
+  border-color: #E4E4E4 #D2D2D2 #B4B4B4;
+  border-radius: 10px;
+  color: #fff;
+  cursor: pointer;
+  display: block;
+  float: left;
+  height: 16px;
+  margin: 13px 0 0;
+  -moz-border-radius: 10px;
+  overflow: hidden;
+  padding: 2px 10px;
+}
+
+/* @group FlexiPanda menus (mobile slidy menus) */
+
+.fp-link {
+  color: #686868;
+  font-size: 1.25em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  text-transform: uppercase;
+  white-space: nowrap;
+}
+.fp-mode-slider .fp-list {
+  padding-left: 2em;
+}
+.fp-item .fp-box {
+  padding-bottom: 0.75em;
+  padding-top: 0.75em;
+}
+.fp-handle {
+  top: 0;
+}
+.fp-handle::after,
+.fp-handle::before {
+  background-color: #999;
+  border-radius: 0px;
+  content: " ";
+  display: block;
+  height: 1em;
+  left: 50%;
+  position: absolute;
+  width: 2px;
+}
+.fp-handle::before {
+  -webkit-transform: rotate(-145deg);
+  top: 1.1em;
+}
+.fp-handle::after {
+  -webkit-transform: rotate(145deg);
+  top: 0.3em;
+}
+.fp-return .fp-handle::before,
+.fp-back .fp-handle::before {
+  -webkit-transform: rotate(-35deg);
+}
+.fp-return .fp-handle::after,
+.fp-back .fp-handle::after {
+  -webkit-transform: rotate(35deg);
+}
+.fp-mode-slider .fp-item + .fp-item {
+  border-top: 1px solid #ccc;
+}
+.fp-mode-slider .fp-link {
+  line-height: 1;
+  padding-bottom: 1em;
+  padding-top:  1em;
+}
+.fp-mode-slider .fp-handle {
+  width: 2em;
+}
+.fp-back .fp-handle {
+  left: 0;
+  right: auto;
+}
+#toolbar .fp-back .fp-handle + * {
+  margin-left: 2em;
+  margin-right: 0;
+}
+
+/* end */
diff --git a/core/modules/toolbar/images/toolbar.png b/core/modules/toolbar/images/toolbar.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c9560391e83b322707050c712f48d53488559b7
GIT binary patch
literal 506
zcmV<W0R{evP)<h;3K|Lk000e1NJLTq003kF001Qj1^@s6wB}5m0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzoJmAMRCwC#nXztzFc5}gU?4Bim*^Z;
z7&?H|0p6r<1QTI{mF#_qPI-ew3UJM#RHBO0xb7t))&EN;%V*(}@54ECQAD(W<|79w
z01ya300aUM0D%AmKp+4C5a^MCBuOIPYss>Vmdhn6rOu4~ye=KHsw(k4i=v?Ye$V@!
z8T)zt>L%RFGPNKG#?4o&75(Np6JyYx=Y2Z_&)F{>t8H7}lQx@;_}*n%(&2ERsd&zQ
zljn^CMNveK<BW;oH#ZDJ@xx4G@W^xN7<FA!-}hsphGC$lX>J;WN1mHLYyI}Ru1j$o
ziy!9e7V>zHx3}v$TCdkPyM?E5AqFH(Q}TUZ`@6_~UY9=1EkNgaPP^TXbYefROUJYU
zt?+*cK6@bm0T2j400aUM0D%AmK%g1P(=~ukqY~Kv?P#wW|MqAvNWU47DVV=Pc{<v&
z#{YrTn*kwVD4h8B3pWJPXxd!-smrL4s{7uMYb{^fn}Ql*0mQWbZUY51M6jq!2sOmA
whR}t2L8v4D>xQ6)%nS%>2x`b<>r;RM0P&^IUJvN{@c;k-07*qoM6N<$f_}i^H2?qr

literal 0
HcmV?d00001

diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
new file mode 100644
index 0000000..d0a7b2b
--- /dev/null
+++ b/core/modules/toolbar/js/toolbar.js
@@ -0,0 +1,240 @@
+(function ($) {
+
+"use strict";
+
+Drupal.toolbar = Drupal.toolbar || {};
+
+/**
+ * Attach toggling behavior and notify the overlay of the toolbar.
+ */
+Drupal.behaviors.toolbar = {
+  attach: function(context, settings) {
+    var $toolbar = $(context).find('#toolbar');
+    var $bar = $toolbar.find('.toolbar-bar');
+    var $tray = $toolbar.find('.toolbar-tray');
+    var $toggle = $toolbar.find('.toggle-tray');
+    // Set the initial state of the toolbar.
+    $bar.once('toolbar-bar', function (index, element) {
+      var $toolbar = $(this);
+      $toolbar.data('drupalToolbar', new Drupal.ToolBar($toolbar));
+    });
+    // Instantiate the toolbar tray.
+    $tray.once('toolbar-slider', function (index, element) {
+      var $tray = $(this);
+      $tray.data('drupalToolbar', new Drupal.TraySlider($tray, $toggle));
+    });
+  }
+};
+
+Drupal.ToolBar = function ($toolbar) {
+  this.$toolbar = $toolbar;
+  this.labels;
+  this.collapsed;
+  // Init the object.
+  this.init.apply(this, arguments);
+};
+/**
+ *
+ */
+Drupal.ToolBar.prototype.init = function() {
+  // Labels
+  this.labels = {
+    'opened': Drupal.t('Hide shortcuts'),
+    'closed': Drupal.t('Show shortcuts')
+  };
+  // Set up the toolbar drawer visibility toggle.
+  this.$toggle = this.$toolbar.find('.toggle-drawer');
+  this.$toggle
+  .on('click.DrupalToolbar', $.proxy(this, 'toggle'));
+  // Store the shortcut bar drawer HTML element.
+  this.$drawer = this.$toolbar.find('.toolbar-drawer');
+  // Retrieve the collapsed status from a stored cookie.
+  this.collapsed = $.cookie('Drupal.toolbar.collapsed');
+  // Expand or collapse the toolbar based on the cookie value.
+  if (this.collapsed === '1') {
+    this.collapse();
+  }
+  else {
+    this.expand();
+  }
+};
+/**
+ * Collapse the toolbar.
+ */
+Drupal.ToolBar.prototype.collapse = function() {
+  var toggle_text = this.labels.closed;
+  this.$drawer.addClass('collapsed');
+  this.$toggle
+  .removeClass('active')
+  .attr('title',  toggle_text)
+  .html(toggle_text);
+  // Remove the class from the body that would indicate the drawer is open.
+  $('body')
+  .removeClass('toolbar-drawer');
+  // Set the height of the toolbar.
+  this.setHeight();
+};
+
+/**
+ * Expand the toolbar.
+ */
+Drupal.ToolBar.prototype.expand = function() {
+  var toggle_text = this.labels.opened;
+  this.$drawer.removeClass('collapsed');
+  this.$toggle
+  .addClass('active')
+  .attr('title',  toggle_text)
+  .html(toggle_text);
+  // Add a class to the body to indicate the drawer is open.
+  $('body').addClass('toolbar-drawer');
+  // Set the height of the toolbar.
+  this.setHeight();
+};
+
+/**
+ * Toggle the toolbar.
+ */
+Drupal.ToolBar.prototype.toggle = function(event) {
+  event.preventDefault();
+  if (this.collapsed === '1') {
+    this.expand();
+    this.collapsed = '0';
+  }
+  else {
+    this.collapse();
+    this.collapsed = '1';
+  }
+  // Store the drawer state in a cookie.
+  $.cookie(
+    'Drupal.toolbar.collapsed',
+    this.collapsed,
+    {
+      path: Drupal.settings.basePath,
+      // The cookie should "never" expire.
+      expires: 36500
+    }
+  );
+};
+
+Drupal.ToolBar.prototype.setHeight = function() {
+  this.height = this.$toolbar.outerHeight();
+  this.$toolbar.attr('data-offset-top', this.height);
+  // Alter the padding on the top of the body element.
+  // @todo, this should be moved to drupal.js and register for
+  // the offsettopchange event.
+  $('body').css('paddingTop', this.height);
+  $(document).trigger('offsettopchange');
+};
+/**
+ *
+ */
+Drupal.TraySlider = function ($tray, $toggle) {
+  this.$tray = $tray;
+  this.$toggle = $toggle;
+  this.state;
+  this.width;
+  this.maxWidth;
+  // Init the object.
+  this.init.apply(this, arguments);
+};
+/**
+ *
+ */
+Drupal.TraySlider.prototype.init = function () {
+  this.state = 'closed';
+  this.maxWidth = 200;
+  this.width = this.getWidth();
+  // Place the menu off screen.
+  this.$tray.css({
+    'width': this.width,
+    'left': this.width * -1
+  });
+  // Add a click handler to the toggle.
+  this.$toggle
+  .on('click.DrupalToolbar', $.proxy(this, 'toggle'));
+  // Register for offsettopchange events.
+  $(document)
+  .on({
+    // Offset value vas changed by a third party script.
+    'offsettopchange.DrupalToolbar': $.proxy(this, 'displace')
+  });
+  this.displace();
+  // Turn on flexiPanda
+  this.$tray.find('.toolbar-menu > .menu').flexiPanda({
+    debug: false,
+    mode: 'slider'
+  });
+};
+/**
+ *
+ */
+Drupal.TraySlider.prototype.toggle = function (event) {
+  event.preventDefault();
+  event.stopImmediatePropagation();
+  if (this.state === 'closed') {
+    this.expand();
+  }
+  else {
+    this.collapse();
+  }
+}
+/**
+ *
+ */
+Drupal.TraySlider.prototype.expand = function (event) {
+  this.width = this.getWidth();
+  this.$tray.animate({
+    'width': this.width,
+    'left': 0
+  });
+  $('body').animate({
+    'padding-left': this.width
+  });
+  this.state = 'open';
+};
+/**
+ *
+ */
+Drupal.TraySlider.prototype.collapse = function () {
+  this.$tray.animate({
+    'left': this.width * -1
+  });
+  $('body').animate({
+    'padding-left': 0
+  });
+  this.state = 'closed';
+};
+/**
+ *
+ */
+Drupal.TraySlider.prototype.displace = function (event) {
+  this.$tray.css({
+    'top': this.computeOffsetTop()
+  });
+};
+/**
+ * Sum all [data-offset-top] values and cache it.
+ * @todo move this out of tableheader.js into a move generic place like drupal.js.
+ */
+Drupal.TraySlider.prototype.computeOffsetTop = function () {
+  var $offsets = $('[data-offset-top]');
+  var value, sum = 0;
+  for (var i = 0, il = $offsets.length; i < il; i++) {
+    value = parseInt($offsets[i].getAttribute('data-offset-top'), 10);
+    sum += !isNaN(value) ? value : 0;
+  }
+  this.offsetTop = sum;
+  return sum;
+};
+/**
+ *
+ */
+Drupal.TraySlider.prototype.getWidth = function (event) {
+  var maxClient = document.documentElement.clientWidth;
+  var candidate = maxClient * 0.9;
+  var width = (candidate > this.maxWidth) ? this.maxWidth : candidate;
+  return width;
+};
+
+
+})(jQuery);
diff --git a/core/modules/toolbar/toolbar-rtl.css b/core/modules/toolbar/toolbar-rtl.css
deleted file mode 100644
index e121547..0000000
--- a/core/modules/toolbar/toolbar-rtl.css
+++ /dev/null
@@ -1,37 +0,0 @@
-
-#toolbar,
-#toolbar * {
-  text-align: right;
-}
-#toolbar ul li {
-  float: right;
-}
-#toolbar ul li a {
-  display: inline-block;
-  float: none;
-  zoom: 1;
-}
-#toolbar div.toolbar-menu {
-  padding: 5px 50px 5px 50px;
-}
-#toolbar-user {
-  float: left;
-}
-#toolbar ul#toolbar-user li {
-  float: none;
-  display: inline;
-}
-#toolbar-menu {
-  float: none;
-}
-#toolbar-home {
-  float: right;
-}
-#toolbar ul li.home a {
-  position: absolute;
-  right: 10px;
-}
-#toolbar div.toolbar-menu a.toggle {
-  left: 10px;
-  right: auto;
-}
diff --git a/core/modules/toolbar/toolbar.css b/core/modules/toolbar/toolbar.css
deleted file mode 100644
index bd18110..0000000
--- a/core/modules/toolbar/toolbar.css
+++ /dev/null
@@ -1,129 +0,0 @@
-
-body.toolbar {
-  padding-top: 2.2em;
-}
-body.toolbar-drawer {
-  padding-top: 5.3em;
-}
-
-/**
- * Aggressive resets so we can achieve a consistent look in hostile CSS
- * environments.
- */
-#toolbar,
-#toolbar * {
-  border: 0;
-  font-size: 100%;
-  line-height: inherit;
-  list-style: none;
-  margin: 0;
-  outline: 0;
-  padding: 0;
-  text-align: left; /* LTR */
-  vertical-align: baseline;
-}
-
-/**
- * Base styles.
- *
- * We use a keyword for the toolbar font size to make it display consistently
- * across different themes, while still allowing browsers to resize the text.
- */
-#toolbar {
-  background: #666;
-  color: #ccc;
-  font: normal small "Lucida Grande", Verdana, sans-serif;
-  left: 0;
-  margin: 0 -20px;
-  padding: 0 20px;
-  position: fixed;
-  right: 0;
-  top: 0;
-  box-shadow: 0 3px 20px #000;
-  z-index: 600;
-}
-#toolbar div.collapsed {
-  display: none;
-  visibility: hidden;
-}
-#toolbar a {
-  color: #fff;
-  font-size: .846em;
-  text-decoration: none;
-}
-#toolbar ul li,
-#toolbar ul li a {
-  float: left; /* LTR */
-}
-
-/**
- * Administration menu.
- */
-#toolbar div.toolbar-menu {
-  background: #000;
-  line-height: 20px;
-  padding: 5px 50px 5px 10px; /* LTR */
-  position: relative;
-}
-#toolbar-home a span {
-  background: url(toolbar.png) no-repeat 0 -45px;
-  display: block;
-  height: 14px;
-  margin: 3px 0px;
-  text-indent: -9999px;
-  vertical-align: text-bottom;
-  width: 11px;
-}
-#toolbar-user {
-  float: right; /* LTR */
-}
-#toolbar-menu {
-  float: left; /* LTR */
-}
-#toolbar div.toolbar-menu a.toggle {
-  background: url(toolbar.png) 0 -20px no-repeat;
-  bottom: 0;
-  cursor: pointer;
-  height: 25px;
-  overflow: hidden;
-  position: absolute;
-  right: 10px; /* LTR */
-  text-indent: -9999px;
-  width: 25px;
-}
-#toolbar div.toolbar-menu a.toggle:focus,
-#toolbar div.toolbar-menu a.toggle:hover {
-  background-position:  -50px -20px;
-}
-#toolbar div.toolbar-menu a.toggle-active {
-  background-position:  -25px -20px;
-}
-#toolbar div.toolbar-menu a.toggle-active.toggle:focus,
-#toolbar div.toolbar-menu a.toggle-active.toggle:hover {
-  background-position:  -75px -20px;
-}
-#toolbar div.toolbar-menu ul li a {
-  padding: 0 10px;
-  border-radius: 10px;
-}
-#toolbar div.toolbar-menu ul li a:focus,
-#toolbar div.toolbar-menu ul li a:hover,
-#toolbar div.toolbar-menu ul li a:active,
-#toolbar div.toolbar-menu ul li a.active:focus {
-  background: #444;
-}
-#toolbar div.toolbar-menu ul li a.active:hover,
-#toolbar div.toolbar-menu ul li a.active:active,
-#toolbar div.toolbar-menu ul li a.active,
-#toolbar div.toolbar-menu ul li.active-trail a {
-  background: url(toolbar.png) 0 0 repeat-x;
-  text-shadow: #333 0 1px 0;
-}
-
-/**
- * Collapsed drawer of additional toolbar content.
- */
-#toolbar div.toolbar-drawer {
-  position: relative;
-  padding: 0 10px;
-}
diff --git a/core/modules/toolbar/toolbar.js b/core/modules/toolbar/toolbar.js
deleted file mode 100644
index 2353050..0000000
--- a/core/modules/toolbar/toolbar.js
+++ /dev/null
@@ -1,115 +0,0 @@
-(function ($) {
-
-"use strict";
-
-Drupal.toolbar = Drupal.toolbar || {};
-
-/**
- * Attach toggling behavior and notify the overlay of the toolbar.
- */
-Drupal.behaviors.toolbar = {
-  attach: function(context, settings) {
-    var $toolbar = $('#toolbar').once('toolbar');
-    if ($toolbar.length) {
-
-      // Set the initial state of the toolbar.
-      Drupal.toolbar.init();
-
-      $(window).on('resize.toolbar', Drupal.toolbar.height);
-
-      // Toggling toolbar drawer.
-      $toolbar.find('a.toggle').once('toolbar-toggle').click(function(e) {
-        e.preventDefault();
-        Drupal.toolbar.toggle();
-        // Allow resize event handlers to recalculate sizes/positions.
-        $(window).triggerHandler('resize');
-      });
-    }
-  }
-};
-
-/**
- * Retrieve last saved cookie settings and set up the initial toolbar state.
- */
-Drupal.toolbar.init = function() {
-  // Retrieve the collapsed status from a stored cookie.
-  var collapsed = $.cookie('Drupal.toolbar.collapsed');
-
-  // Expand or collapse the toolbar based on the cookie value.
-  if (collapsed === '1') {
-    Drupal.toolbar.collapse();
-  }
-  else {
-    Drupal.toolbar.expand();
-  }
-};
-
-/**
- * Collapse the toolbar.
- */
-Drupal.toolbar.collapse = function() {
-  var toggle_text = Drupal.t('Show shortcuts');
-  $('#toolbar div.toolbar-drawer').addClass('collapsed');
-  $('#toolbar a.toggle')
-    .removeClass('toggle-active')
-    .attr('title',  toggle_text)
-    .html(toggle_text);
-  $('body').removeClass('toolbar-drawer').css('paddingTop', Drupal.toolbar.height());
-  $.cookie(
-    'Drupal.toolbar.collapsed',
-    1,
-    {
-      path: Drupal.settings.basePath,
-      // The cookie should "never" expire.
-      expires: 36500
-    }
-  );
-  Drupal.toolbar.height();
-  $(document).trigger('offsettopchange');
-};
-
-/**
- * Expand the toolbar.
- */
-Drupal.toolbar.expand = function() {
-  var toggle_text = Drupal.t('Hide shortcuts');
-  $('#toolbar div.toolbar-drawer').removeClass('collapsed');
-  $('#toolbar a.toggle')
-    .addClass('toggle-active')
-    .attr('title',  toggle_text)
-    .html(toggle_text);
-  $('body').addClass('toolbar-drawer').css('paddingTop', Drupal.toolbar.height());
-  $.cookie(
-    'Drupal.toolbar.collapsed',
-    0,
-    {
-      path: Drupal.settings.basePath,
-      // The cookie should "never" expire.
-      expires: 36500
-    }
-  );
-  Drupal.toolbar.height();
-  $(document).trigger('offsettopchange');
-};
-
-/**
- * Toggle the toolbar.
- */
-Drupal.toolbar.toggle = function() {
-  if ($('#toolbar div.toolbar-drawer').hasClass('collapsed')) {
-    Drupal.toolbar.expand();
-  }
-  else {
-    Drupal.toolbar.collapse();
-  }
-};
-
-Drupal.toolbar.height = function() {
-  // @TODO this needs to be cached outside this function.
-  var $toolbar = $('#toolbar');
-  var height = $toolbar.outerHeight();
-  $toolbar.attr('data-offset-top', height);
-  return height;
-};
-
-})(jQuery);
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index fa4dd6f..379673a 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -116,10 +116,10 @@ function _toolbar_is_collapsed() {
 /**
  * Implements hook_page_build().
  *
- * Add admin toolbar to the page_top region automatically.
+ * Add admin toolbar to the page_bottom region automatically.
  */
 function toolbar_page_build(&$page) {
-  $page['page_top']['toolbar'] = array(
+  $page['page_bottom']['toolbar'] = array(
     '#pre_render' => array('toolbar_pre_render'),
     '#access' => user_access('access toolbar'),
     'toolbar_drawer' => array(),
@@ -145,7 +145,7 @@ function toolbar_pre_render($toolbar) {
  * Add some page classes, so global page theming can adjust to the toolbar.
  */
 function toolbar_preprocess_html(&$vars) {
-  if (isset($vars['page']['page_top']['toolbar']) && user_access('access toolbar')) {
+  if (isset($vars['page']['page_bottom']['toolbar']) && user_access('access toolbar')) {
     $vars['attributes']['class'][] = 'toolbar';
     if (!_toolbar_is_collapsed()) {
       $vars['attributes']['class'][] = 'toolbar-drawer';
@@ -166,7 +166,7 @@ function toolbar_preprocess_toolbar(&$variables) {
 /**
  * Implements hook_system_info_alter().
  *
- * Indicate that the 'page_top' region (in which the toolbar will be displayed)
+ * Indicate that the 'page_bottom' region (in which the toolbar will be displayed)
  * is an overlay supplemental region that should be refreshed whenever its
  * content is updated.
  *
@@ -175,7 +175,7 @@ function toolbar_preprocess_toolbar(&$variables) {
  */
 function toolbar_system_info_alter(&$info, $file, $type) {
   if ($type == 'theme') {
-    $info['overlay_supplemental_regions'][] = 'page_top';
+    $info['overlay_supplemental_regions'][] = 'page_bottom';
   }
 }
 
@@ -198,12 +198,17 @@ function toolbar_view() {
   );
 
   // Retrieve the admin menu from the database.
-  $links = toolbar_menu_navigation_links(toolbar_get_menu_tree());
-  $build['toolbar_menu'] = array(
-    '#theme' => 'links__toolbar_menu',
-    '#links' => $links,
-    '#attributes' => array('id' => 'toolbar-menu'),
-    '#heading' => array('text' => t('Administrative toolbar'), 'level' => 'h2', 'class' => 'element-invisible'),
+  $tree = toolbar_get_menu_tree();
+  // Add attributes to the links before rendering.
+  toolbar_menu_navigation_links($tree);
+  $build['toolbar_menu'] = menu_tree_output($tree);
+
+  $build['toolbar_filter'] = array(
+    '#type' => 'search',
+    '#attributes' => array(
+      'class' => array('filter'),
+      'placeholder' => t('Search'),
+    ),
   );
 
   // Add logout & user account links or login link.
@@ -232,29 +237,38 @@ function toolbar_view() {
   $build['toolbar_user'] = array(
     '#theme' => 'links__toolbar_user',
     '#links' => $links,
-    '#attributes' => array('id' => 'toolbar-user'),
+    '#attributes' => array(
+      'id' => 'toolbar-user',
+      'class' => array('menu'),
+    ),
   );
 
   // Add a "home" link.
   $link = array(
     'home' => array(
-      'title' => '<span class="home-link">Home</span>',
+      'title' => 'Home',
       'href' => '<front>',
-      'html' => TRUE,
-      'attributes' => array('title' => t('Home')),
+      'html' => FALSE,
+      'attributes' => array(
+        'title' => t('Home'),
+        'class' => array('button', 'home-link'),
+      ),
     ),
   );
   $build['toolbar_home'] = array(
     '#theme' => 'links',
     '#links' => $link,
-    '#attributes' => array('id' => 'toolbar-home'),
+    '#attributes' => array(
+      'id' => 'toolbar-home',
+      'class' => array('menu'),
+    ),
   );
 
   // Add an anchor to be able to toggle the visibility of the drawer.
   $build['toolbar_toggle'] = array(
     '#theme' => 'toolbar_toggle',
     '#collapsed' => _toolbar_is_collapsed(),
-    '#attributes' => array('class' => array('toggle')),
+    '#attributes' => array('class' => array('button', 'toggle', 'toggle-drawer',)),
   );
 
   // Prepare the drawer links CSS classes.
@@ -267,6 +281,20 @@ function toolbar_view() {
   }
   $build['toolbar_drawer']['#type'] = 'container';
   $build['toolbar_drawer']['#attributes']['class'] = $toolbar_drawer_classes;
+  
+  // Append the admin tray toggle.
+  $build['toolbar_tray_toggle'] = array(
+    '#heading' => array('text' => t('Administrative tray toggle'), 'level' => 'h2', 'class' => 'element-invisible'),
+    '#theme' => 'link',
+    '#path' => 'admin',
+    '#text' => t('Admin tray'),
+    '#options' => array(
+      'attributes' => array(
+        'class' => array('button', 'toggle', 'toggle-tray'),
+      ),
+      'html' => FALSE,
+    ),
+  );
 
   return $build;
 }
@@ -281,14 +309,13 @@ function toolbar_get_menu_tree() {
   $tree = array();
   $admin_link = db_query('SELECT * FROM {menu_links} WHERE menu_name = :menu_name AND module = :module AND link_path = :path', array(':menu_name' => 'management', ':module' => 'system', ':path' => 'admin'))->fetchAssoc();
   if ($admin_link) {
-    $tree = menu_build_tree('management', array(
-      'expanded' => array($admin_link['mlid']),
-      'min_depth' => $admin_link['depth'] + 1,
-      'max_depth' => $admin_link['depth'] + 1,
-    ));
+    $tree = menu_tree_all_data('management');
   }
-
-  return $tree;
+  // Return the sub-menus of the management menu root.
+  foreach ($tree as $key => $menu) {
+    return (!empty($tree[$key]['below'])) ? $tree[$key]['below'] : array();
+  }
+  return array();
 }
 
 /**
@@ -300,34 +327,16 @@ function toolbar_get_menu_tree() {
  * @return
  *   An array of links as defined above.
  */
-function toolbar_menu_navigation_links($tree) {
-  $links = array();
-  foreach ($tree as $item) {
-    if (!$item['link']['hidden'] && $item['link']['access']) {
-      // Make sure we have a path specific ID in place, so we can attach icons
-      // and behaviors to the items.
-      $id = str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['href']);
-
-      $link = $item['link']['localized_options'];
-      $link['href'] = $item['link']['href'];
-      // Add icon placeholder.
-      $link['title'] = '<span class="icon"></span>' . check_plain($item['link']['title']);
-      // Add admin link ID.
-      $link['attributes'] = array('id' => 'toolbar-link-' . $id);
-      if (!empty($item['link']['description'])) {
-        $link['title'] .= ' <span class="element-invisible">(' . $item['link']['description'] . ')</span>';
-        $link['attributes']['title'] = $item['link']['description'];
-      }
-      $link['html'] = TRUE;
-
-      $class = ' path-' . $id;
-      if (toolbar_in_active_trail($item['link']['href'])) {
-        $class .= ' active-trail';
-      }
-      $links['menu-' . $item['link']['mlid'] . $class] = $link;
+function toolbar_menu_navigation_links(&$tree) {
+  foreach ($tree as $key => $item) {
+    // Configure sub-items.
+    if (!empty($item['below'])) {
+      toolbar_menu_navigation_links($tree[$key]['below']);
     }
+    // Make sure we have a path specific ID in place, so we can attach icons
+    // and behaviors to the items.
+    $tree[$key]['link']['localized_options']['attributes']['id'] = 'toolbar-link-' . str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['link_path']);
   }
-  return $links;
 }
 
 /**
@@ -366,10 +375,11 @@ function toolbar_library_info() {
     'title' => 'Toolbar',
     'version' => VERSION,
     'js' => array(
-      drupal_get_path('module', 'toolbar') . '/toolbar.js' => array(),
+      drupal_get_path('module', 'toolbar') . '/js/toolbar.js' => array(),
     ),
     'css' => array(
-      drupal_get_path('module', 'toolbar') . '/toolbar.css',
+      drupal_get_path('module', 'toolbar') . '/css/toolbar.base.css',
+      drupal_get_path('module', 'toolbar') . '/css/toolbar.theme.css',
     ),
     'dependencies' => array(
       array('system', 'jquery'),
@@ -377,6 +387,7 @@ function toolbar_library_info() {
       array('system', 'drupal.settings'),
       array('system', 'jquery.once'),
       array('system', 'jquery.cookie'),
+      array('system', 'jquery.flexipanda'),
     ),
   );
 
diff --git a/core/modules/toolbar/toolbar.png b/core/modules/toolbar/toolbar.png
deleted file mode 100644
index f2c7f355a6d9d8acb478f25a74ec1670cde26445..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 558
zcmeAS@N?(olHy`uVBq!ia0vp^DL`z=!3-q7>(u!JsqFziA+A9B|NsAKX=!j0$Up`_
zDF^_nWMpJyVq#)uW@cew;o#t~wY9agvvYTM_weut2nYxa42+0~04i>1XlQC`YH4X{
zZEbCDZ|~^n=<4d~>FMe1?d|XHpD<y<q)C&eOqnuu>eT7er_Y!%W7e!$bLPyMJ9qB<
z`SX`AU%qbLy7lYVZ{NOs$BrEb4<0;p=+O7?-+%x9{pZi0zkmP!`}Ys%yrsn~H-HY}
zD+%%oW?&GIZRqIkn>cmmg$Ez}_rz5JT`J+};uunK>+R)e|3eM}Z4dJ|aEYwo2;*D4
zsOh<|h~SZ*|Mz>F_Znul2~2v|(p{_fEluy<T~D$1Y#-7X*0X&`VmQzCA%&rz?Lz{?
zcea9bhV5(yh7B7T??@cj$`~Vg-~@vn?}I}O=Xe=9X2o3T33#>OQiAW|phpaXuNMii
zXKY*-`iLP%!Nuu_#-;S58)jSFRn#^L^O^ogXL*#0uV19$i$7*o%walDCW~&K+Oa0>
zmUq?LCqH_+KRNC`-t{wTpS>B+wc^y+pRN8^dY5|c`gkaQ=D#DX;!4rs_wVoewMggB
zWC6~JwLKOtHyGdYoI9vk*&m?e{>0KLRB+{_>l{~)tekk9<Em=7di}(Re@Ff)eL5e1
hBy_@j#ZB@P<q!DTXx&t5{QwL-22WQ%mvv4FO#l<-22ub3

diff --git a/core/modules/toolbar/toolbar.tpl.php b/core/modules/toolbar/toolbar.tpl.php
index 5b03fee..e855fa7 100644
--- a/core/modules/toolbar/toolbar.tpl.php
+++ b/core/modules/toolbar/toolbar.tpl.php
@@ -20,14 +20,20 @@
  */
 ?>
 <nav id="toolbar" role="navigation" class="<?php print $attributes['class']; ?> clearfix" <?php print $attributes; ?>>
-  <div class="toolbar-menu clearfix">
+  <div class="toolbar-bar clearfix">
     <?php print render($toolbar['toolbar_home']); ?>
     <?php print render($toolbar['toolbar_user']); ?>
-    <?php print render($toolbar['toolbar_menu']); ?>
-    <?php if ($toolbar['toolbar_drawer']):?>
-      <?php print render($toolbar['toolbar_toggle']); ?>
-    <?php endif; ?>
+    <?php print render($toolbar['toolbar_tray_toggle']); ?>
   </div>
 
-  <?php print render($toolbar['toolbar_drawer']); ?>
+  <div class="toolbar-tray">
+    <div class="lining">
+      <?php print render($toolbar['toolbar_filter']); ?>
+      <?php print render($toolbar['toolbar_drawer']); ?>
+      <nav class="toolbar-menu">
+        <h2 class="element-invisible"><?php print t('Administration menu'); ?></h2>
+        <?php print render($toolbar['toolbar_menu']); ?>
+      </nav>
+    </div>
+  </div>
 </nav>
-- 
1.7.10.4

