text: /**
   * @file
   * Javascript required for a simple collapsible div.
   *
   * Creating a collapsible div with this doesn't take too much. There are
   * three classes necessary:
   *
   * - ctools-collapsible-container: This is the overall container that will be
   *   collapsible. This must be a div.
   * - ctools-collapsible-handle: This is the title area, and is what will be
   *   visible when it is collapsed. This can be any block element, such as div
   *   or h2.
   * - ctools-collapsible-content: This is the ocntent area and will only be
   *   visible when expanded. This must be a div.
   *
   * Adding 'ctools-collapsible-remember' to the container class will cause the
   * state of the container to be stored in a cookie, and remembered from page
   * load to page load. This will only work if the container has a unique ID, so
   * very carefully add IDs to your containers.
   *
   * If the class 'ctools-no-container' is placed on the container, the container
   * will be the handle. The content will be found by appending '-content' to the
   * id of the handle. The ctools-collapsible-handle and
   * ctools-collapsible-content classes will not be required in that case, and no
   * restrictions on what of data the container is are placed. Like
   * ctools-collapsible-remember this requires an id to eist.
   *
   * The content will be 'open' unless the container class has 'ctools-collapsed'
   * as a class, which will cause the container to draw collapsed.
   */
  
  (function ($) {
    // All CTools tools begin with this if they need to use the CTools namespace.
    if (!Drupal.CTools) {
      Drupal.CTools = {};
    }
  
    /**
     * Object to store state.
     *
     * This object will remember the state of collapsible containers. The first
     * time a state is requested, it will check the cookie and set up the variable.
     * If a state has been changed, when the window is unloaded the state will be
     * saved.
     */
    Drupal.CTools.Collapsible = {
      state: {},
      stateLoaded: false,
      stateChanged: false,
      cookieString: 'ctools-collapsible-state=',
  
      /**
       * Get the current collapsed state of a container.
       *
       * If set to 1, the container is open. If set to -1, the container is
       * collapsed. If unset the state is unknown, and the default state should
       * be used.
       */
      getState: function (id) {
        if (!this.stateLoaded) {
          this.loadCookie();
        }
  
        return this.state[id];
      },
  
      /**
       * Set the collapsed state of a container for subsequent page loads.
       *
       * Set the state to 1 for open, -1 for collapsed.
       */
      setState: function (id, state) {
        if (!this.stateLoaded) {
          this.loadCookie();
        }
  
        this.state[id] = state;
  
        if (!this.stateChanged) {
          this.stateChanged = true;
          $(window).unload(this.unload);
        }
      },
  
      /**
       * Check the cookie and load the state variable.
       */
      loadCookie: function () {
        // If there is a previous instance of this cookie
        if (document.cookie.length > 0) {
          // Get the number of characters that have the list of values
          // from our string index.
          offset = document.cookie.indexOf(this.cookieString);
  
          // If its positive, there is a list!
          if (offset != -1) {
            offset += this.cookieString.length;
            var end = document.cookie.indexOf(';', offset);
            if (end == -1) {
              end = document.cookie.length;
            }
  
            // Get a list of all values that are saved on our string
            var cookie = unescape(document.cookie.substring(offset, end));
  
            if (cookie != '') {
              var cookieList = cookie.split(',');
              for (var i = 0; i < cookieList.length; i++) {
                var info = cookieList[i].split(':');
                this.state[info[0]] = info[1];
              }
            }
          }
        }
  
        this.stateLoaded = true;
      },
  
      /**
       * Turn the state variable into a string and store it in the cookie.
       */
      storeCookie: function () {
        var cookie = '';
  
        // Get a list of IDs, saparated by comma
        for (i in this.state) {
          if (cookie != '') {
            cookie += ',';
          }
          cookie += i + ':' + this.state[i];
        }
  
        // Save this values on the cookie
        document.cookie = this.cookieString + escape(cookie) + ';path=/';
      },
  
      /**
       * Respond to the unload event by storing the current state.
       */
      unload: function() {
        Drupal.CTools.Collapsible.storeCookie();
      }
    };
  
    // Set up an array for callbacks.
    Drupal.CTools.CollapsibleCallbacks = [];
    Drupal.CTools.CollapsibleCallbacksAfterToggle = [];
  
    /**
     * Bind collapsible behavior to a given container.
     */
    Drupal.CTools.bindCollapsible = function () {
      var $container = $(this);
  
      // Allow the specification of the 'no container' class, which means the
      // handle and the container can be completely independent.
      if ($container.hasClass('ctools-no-container') && $container.attr('id')) {
        // In this case, the container *is* the handle and the content is found
        // by adding '-content' to the id. Obviously, an id is required.
        var handle = $container;
        var content = $('#' + $container.attr('id') + '-content');
      }
      else {
        var handle = $container.children('.ctools-collapsible-handle');
        var content = $container.children('div.ctools-collapsible-content');
      }
  
      if (content.length) {
        // Create the toggle item and place it in front of the toggle.
        var toggle = $('<span class="ctools-toggle"></span>');
        handle.before(toggle);
  
        // If the remember class is set, check to see if we have a remembered
        // state stored.
        if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
          var state = Drupal.CTools.Collapsible.getState($container.attr('id'));
          if (state == 1) {
            $container.removeClass('ctools-collapsed');
          }
          else if (state == -1) {
            $container.addClass('ctools-collapsed');
          }
        }
  
        // If we should start collapsed, do so:
        if ($container.hasClass('ctools-collapsed')) {
          toggle.toggleClass('ctools-toggle-collapsed');
          content.hide();
        }
  
        var afterToggle = function () {
          if (Drupal.CTools.CollapsibleCallbacksAfterToggle) {
            for (i in Drupal.CTools.CollapsibleCallbacksAfterToggle) {
              Drupal.CTools.CollapsibleCallbacksAfterToggle[i]($container, handle, content, toggle);
            }
          }
        }
  
        var clickMe = function () {
          if (Drupal.CTools.CollapsibleCallbacks) {
            for (i in Drupal.CTools.CollapsibleCallbacks) {
              Drupal.CTools.CollapsibleCallbacks[i]($container, handle, content, toggle);
            }
          }
  
          // If the container is a table element slideToggle does not do what
          // we want, so use toggle() instead.
          if ($container.is('table')) {
            content.toggle(0, afterToggle);
          }
          else {
            content.slideToggle(100, afterToggle);
          }
  
          toggle.toggleClass('ctools-toggle-collapsed');
  
          // If we're supposed to remember the state of this class, do so.
          if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
            var state = toggle.hasClass('ctools-toggle-collapsed') ? -1 : 1;
            Drupal.CTools.Collapsible.setState($container.attr('id'), state);
          }
        }
  
        // Let both the toggle and the handle be clickable.
        toggle.click(clickMe);
        handle.click(clickMe);
      }
    };
  
    /**
     * Support Drupal's 'behaviors' system for binding.
     */
    Drupal.behaviors.CToolsCollapsible = { 
      attach: function(context) {
        $('.ctools-collapsible-container:not(.ctools-collapsible-processed)', context)
          .each(Drupal.CTools.bindCollapsible)
          .addClass('ctools-collapsible-processed');
      }
    }
  })(jQuery);
  