popsu-d7/sites/all/modules/ctools/js/collapsible-div.js
2015-04-26 18:38:56 +02:00

242 lines
7.8 KiB
JavaScript

/**
* @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);
}
$container.toggleClass('ctools-collapsed');
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);
}
return false;
}
// 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', context).once('ctools-collapsible', Drupal.CTools.bindCollapsible);
}
}
})(jQuery);