From cf704ca346a2a900441ed813ebe4a05362df5aff Mon Sep 17 00:00:00 2001
From: Katherine Bailey <katherine@katbailey.net>
Date: Wed, 23 Nov 2011 15:30:19 -0800
Subject: [PATCH] Issue #1350832: Refactor the JS for the bbq/history
 integration for accordion and ui tabs

---
 js/qt_accordion.js         |   72 +++++-------------------------------------
 js/qt_ui_tabs.js           |   76 +++++++++-----------------------------------
 js/quicktabs_bbq.js        |   37 +++++++++++++++++++++
 plugins/QuickAccordion.inc |   18 +++++++---
 plugins/QuickUiTabs.inc    |   17 +++++++++-
 5 files changed, 89 insertions(+), 131 deletions(-)
 create mode 100644 js/quicktabs_bbq.js

diff --git a/js/qt_accordion.js b/js/qt_accordion.js
index b6083a5..83a94a9 100644
--- a/js/qt_accordion.js
+++ b/js/qt_accordion.js
@@ -2,77 +2,21 @@
 
 Drupal.behaviors.qt_accordion = {
   attach: function (context, settings) {
-    var qt_options = Drupal.settings.quicktabs;
-    var history_enabled = false;
     $('.quick-accordion', context).once(function(){
+      var id = $(this).attr('id');
       var qtKey = 'qt_' + this.id.substring(this.id.indexOf('-') +1);
-      var options = Drupal.settings.quicktabs[qtKey].options;
-      if (options.history) {
-        history_enabled = true;
-      }
-      var active_tab = parseInt(Drupal.settings.quicktabs[qtKey].active_tab);
-      options.active = active_tab;
-      options.event = 'change';
-      $(this).accordion(options).addClass("init");
-    });
-
-    var accordions = $(".quick-accordion", context);
-    var acc_selector = "h3 a";
-
-    // Add href value to links.
-    $(".accordion a").each(function(index, value) {
-      var id = $(this).closest( '.quick-accordion' ).attr( 'id' );
-      $(this).attr("href", "#" + id + "_" + index);
-    });
-
-    accordions.find( acc_selector ).click(function(event){
-      // Keep the link from firing.
-      event.preventDefault();
+      var options = settings.quicktabs[qtKey].options;
 
-      var state = {},
-        id = $(this).closest( '.quick-accordion' ).attr( 'id' ),
-        idx = $(this).parent().prevAll('h3').length,
-        el = id.split("quickset-");
-
-      var key = 'qt_' + el[1];
-      // Only fire if history is set.
-      if (qt_options[key].history) {
-        state[ id ] = idx;
-        $.bbq.pushState( state );
+      options.active = parseInt(settings.quicktabs[qtKey].active_tab);
+      if (settings.quicktabs[qtKey].history) {
+        options.event = 'change';
+        $(this).accordion(options);
+        Drupal.quicktabsBbq($(this), 'h3 a', 'h3');
       }
       else {
-        $('#' + id).accordion('activate', idx);
+        $(this).accordion(options);
       }
     });
-
-    if (history_enabled) {
-      $(window).bind( 'hashchange', function(e) {
-        params = $.deparam.fragment();
-        // Should only fire once when page loads.
-        if (accordions.hasClass("init")) {
-          for (var key in qt_options) {
-            var name = 'quickset-' + qt_options[key].name,
-              active_tab = parseInt(qt_options[key].active_tab);
-            // If there is an active tab and the tab isn't already defined by a hash.
-            if (active_tab > 0 && !params[name]) {
-              $("#" + name).accordion('activate', active_tab);
-            }
-          }
-          accordions.removeClass("init");
-        }
-
-        accordions.each(function(){
-          var idx = e.getState( this.id, true );
-          // Only activate tab if it has a hash.
-          if (params[$(this).attr('id')]) {
-            $(this).accordion('activate', idx);
-          }
-        });
-      });
-
-      $(window).trigger( 'hashchange' );
-    }
-
   }
 }
 
diff --git a/js/qt_ui_tabs.js b/js/qt_ui_tabs.js
index d25bc00..ad6b5a8 100644
--- a/js/qt_ui_tabs.js
+++ b/js/qt_ui_tabs.js
@@ -1,67 +1,21 @@
-/**
- * @file
- * Implements JQuery UI and history using BBQ.
- * See http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs
- */
 (function ($) {
-  Drupal.behaviors.qt_ui_tabs = {
-    attach: function (context, settings) {
 
-      options = Drupal.settings.quicktabs;
-      params = $.deparam.fragment();
+Drupal.behaviors.qt_ui_tabs = {
+  attach: function (context, settings) {
 
-      // This selector will be reused when selecting actual tab widget A elements.
-      tab_a_selector = 'ul.ui-tabs-nav a';
+    $('.quicktabs-ui-wrapper').once('qt-ui-tabs-processed', function() {
+      var id = $(this).attr('id');
+      var qtKey = 'qt_' + id.substring(id.indexOf('-') +1);
+      if (!settings.quicktabs[qtKey].history) {
+        $(this).tabs();
+      }
+      else {
+        $(this).tabs({event: 'change'});
+        Drupal.quicktabsBbq($(this), 'ul.ui-tabs-nav a');
+      }
+    });
 
-      var tabs = $('.quicktabs-ui-wrapper').tabs({
-        event: 'change'
-      }).addClass("init");
-
-      // Define our own click handler for the tabs, overriding the default.
-      tabs.find( tab_a_selector ).click(function(){
-        var state = {},
-          
-          // Get the id of this tab widget.
-          id = $(this).closest( '.quicktabs-ui-wrapper' ).attr( 'id' ),
-          
-          // Get the index of this tab.
-          idx = $(this).parent().prevAll().length;
-        
-        el = id.split("quicktabs-");
-        qt_id = 'qt_' + el[1];
-        // Only fire if history is set.
-        if (options[qt_id].history) {
-          state[ id ] = idx;
-          $.bbq.pushState( state );
-        }
-        else {
-          name = 'quicktabs-' + options[qt_id].name;
-          $('#' + name).tabs('select', idx);
-        }
-      });
-      
-      $(window).bind( 'hashchange', function(e) {
-        // Should only fire once when page loads. 
-        if (tabs.hasClass("init")) {
-          for (var key in options) {
-            name = 'quicktabs-' + options[key].name;
-            active_tab = parseInt(options[key].active_tab);
-            // If there is an active tab and the tab isn't already defined by a hash.
-            if (active_tab > 0 && !params[name]) {
-              $("#" + name).tabs('select', active_tab);
-            }
-          }
-          tabs.removeClass("init");
-        }
-        tabs.each(function() {
-          var idx = $.bbq.getState( this.id, true );
-          $(this).find( tab_a_selector ).eq( idx ).triggerHandler( 'change' );
-        });
-
-      })
-      
-      $(window).trigger( 'hashchange' );
-
-    }
   }
+}
+
 })(jQuery);
diff --git a/js/quicktabs_bbq.js b/js/quicktabs_bbq.js
new file mode 100644
index 0000000..72dc60b
--- /dev/null
+++ b/js/quicktabs_bbq.js
@@ -0,0 +1,37 @@
+/**
+ * @file
+ * Implements history using the BBQ plugin.
+ * See http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs
+ */
+(function($) {
+
+Drupal.quicktabsBbq = function($tabset, clickSelector, changeSelector) {
+
+  changeSelector = changeSelector || clickSelector;
+
+  // Define our own click handler for the tabs, overriding the default.
+  $(clickSelector, $tabset).each(function(i, el){
+    this.tabIndex = i;
+    $(this).click(function(e){
+      e.preventDefault();
+      var state = {},
+        id = $tabset.attr('id'), // qt container id
+        idx = this.tabIndex; // tab index
+
+      state[id] = idx;
+      $.bbq.pushState(state);
+    });
+  });
+
+  $(window).bind('hashchange', function(e) {
+    $tabset.each(function() {
+      var idx = $.bbq.getState(this.id, true);
+      var $active_link = $(this).find(changeSelector).eq(idx);
+      $active_link.triggerHandler('change');
+    });
+  });
+
+  $(window).trigger('hashchange');
+}
+
+})(jQuery);
\ No newline at end of file
diff --git a/plugins/QuickAccordion.inc b/plugins/QuickAccordion.inc
index abd7015..19666c4 100644
--- a/plugins/QuickAccordion.inc
+++ b/plugins/QuickAccordion.inc
@@ -32,14 +32,14 @@ class QuickAccordion extends QuickRenderer {
   
   public function render() {
     $quickset = $this->quickset;
-
+    $qsid = 'quickset-' . $quickset->getName();
     // Build our render array...
     $render_array = array();
     $render_array['#attached'] = $this->add_attached();
     $render_array['content'] = array(
       '#theme' => 'qt_accordion',
       '#options' => array('attributes' => array(
-        'id' => 'quickset-' . $quickset->getName(),
+        'id' => $qsid,
         'class' => array('quick-accordion'),
       )),
       'divs' => array(),
@@ -49,7 +49,7 @@ class QuickAccordion extends QuickRenderer {
     foreach ($quickset->getContents() as $key => $item) {
       if (!empty($item)) {
         $render_array['content']['divs'][] = array(
-          '#prefix' => '<h3><a href= "#">'. $quickset->translateString($item->getTitle(), 'tab', $key) .'</a></h3><div>',
+          '#prefix' => '<h3><a href= "#'. $qsid . '_' . $key .'">'. $quickset->translateString($item->getTitle(), 'tab', $key) .'</a></h3><div>',
           '#suffix' => '</div>',
           'content' => $item->render(),
         );
@@ -62,6 +62,9 @@ class QuickAccordion extends QuickRenderer {
    * Add any necessary js, css and libraries for the render array.
    */
   protected function add_attached() {
+    $settings = $this->quickset->getSettings();
+    $options = $settings['options'];
+
     $attached = array(
       'library' => array(
         array('system', 'ui.accordion'),
@@ -70,6 +73,7 @@ class QuickAccordion extends QuickRenderer {
         array('data' => drupal_get_path('module', 'quicktabs') . '/js/qt_accordion.js'),
       ),
     );
+
     $javascript = drupal_add_js();
     foreach ($javascript['settings']['data'] as $key => $settings) {
       if (key($settings) == 'quicktabs') {
@@ -77,9 +81,13 @@ class QuickAccordion extends QuickRenderer {
         break;
       }
     }
+
+    if ($options['history']) {
+      $attached['library'][] = array('system', 'jquery.bbq');
+      $attached['js'][] = array('data' => drupal_get_path('module', 'quicktabs') . '/js/quicktabs_bbq.js');
+    }
+
     $name = $this->quickset->getName();
-    $settings = $this->quickset->getSettings();
-    $options = $settings['options'];
     if (!isset($qtkey) || !array_key_exists('qt_' . $name, $javascript['settings']['data'][$qtkey]['quicktabs'])) {
       $quicktabs_array = array('name' => $name, 'active_tab' => $this->quickset->getActiveTab(), 'options' => $options['jquery_ui'], 'history' => $options['history']);
       $attached['js'][] = array('data' => array('quicktabs' => array('qt_'. $name => $quicktabs_array)), 'type' => 'setting');
diff --git a/plugins/QuickUiTabs.inc b/plugins/QuickUiTabs.inc
index 5eedf2f..c8fc421 100644
--- a/plugins/QuickUiTabs.inc
+++ b/plugins/QuickUiTabs.inc
@@ -79,15 +79,30 @@ class QuickUiTabs extends QuickRenderer {
     $active_tab = $this->quickset->getActiveTab();
     $settings = $this->quickset->getSettings();
     $options = $settings['options'];
+
     $attached = array(
       'library' => array(
         array('system', 'ui.tabs'),
 	array('system', 'jquery.bbq'),
       ),
       'js' => array(
-        array('data' => drupal_get_path('module', 'quicktabs') . '/js/qt_ui_tabs.js'),
+        array('data' => drupal_get_path('module', 'quicktabs') . '/js/qt_ui_tabs.js', 'weight' => JS_DEFAULT + 1),
       ),
     );
+
+    $javascript = drupal_add_js();
+    foreach ($javascript['settings']['data'] as $key => $settings) {
+      if (key($settings) == 'quicktabs') {
+        $qtkey = $key;
+        break;
+      }
+    }
+
+    if ($options['history']) {
+      $attached['library'][] = array('system', 'jquery.bbq');
+      $attached['js'][] = array('data' => drupal_get_path('module', 'quicktabs') . '/js/quicktabs_bbq.js', 'weight' => JS_DEFAULT);
+    }
+
     $name = $this->quickset->getName();
     if (!isset($qtkey) || !array_key_exists('qt_' . $name, $javascript['settings']['data'][$qtkey]['quicktabs'])) {
       $quicktabs_array = array('name' => $name, 'active_tab' => $this->quickset->getActiveTab(), 'history' => $options['history']);
-- 
1.7.5.4

