annotate sites/all/modules/ctools/js/collapsible-div.js @ 0:ff03f76ab3fe

initial version
author danieleb <danielebarchiesi@me.com>
date Wed, 21 Aug 2013 18:51:11 +0100
parents
children
rev   line source
danielebarchiesi@0 1 /**
danielebarchiesi@0 2 * @file
danielebarchiesi@0 3 * Javascript required for a simple collapsible div.
danielebarchiesi@0 4 *
danielebarchiesi@0 5 * Creating a collapsible div with this doesn't take too much. There are
danielebarchiesi@0 6 * three classes necessary:
danielebarchiesi@0 7 *
danielebarchiesi@0 8 * - ctools-collapsible-container: This is the overall container that will be
danielebarchiesi@0 9 * collapsible. This must be a div.
danielebarchiesi@0 10 * - ctools-collapsible-handle: This is the title area, and is what will be
danielebarchiesi@0 11 * visible when it is collapsed. This can be any block element, such as div
danielebarchiesi@0 12 * or h2.
danielebarchiesi@0 13 * - ctools-collapsible-content: This is the ocntent area and will only be
danielebarchiesi@0 14 * visible when expanded. This must be a div.
danielebarchiesi@0 15 *
danielebarchiesi@0 16 * Adding 'ctools-collapsible-remember' to the container class will cause the
danielebarchiesi@0 17 * state of the container to be stored in a cookie, and remembered from page
danielebarchiesi@0 18 * load to page load. This will only work if the container has a unique ID, so
danielebarchiesi@0 19 * very carefully add IDs to your containers.
danielebarchiesi@0 20 *
danielebarchiesi@0 21 * If the class 'ctools-no-container' is placed on the container, the container
danielebarchiesi@0 22 * will be the handle. The content will be found by appending '-content' to the
danielebarchiesi@0 23 * id of the handle. The ctools-collapsible-handle and
danielebarchiesi@0 24 * ctools-collapsible-content classes will not be required in that case, and no
danielebarchiesi@0 25 * restrictions on what of data the container is are placed. Like
danielebarchiesi@0 26 * ctools-collapsible-remember this requires an id to eist.
danielebarchiesi@0 27 *
danielebarchiesi@0 28 * The content will be 'open' unless the container class has 'ctools-collapsed'
danielebarchiesi@0 29 * as a class, which will cause the container to draw collapsed.
danielebarchiesi@0 30 */
danielebarchiesi@0 31
danielebarchiesi@0 32 (function ($) {
danielebarchiesi@0 33 // All CTools tools begin with this if they need to use the CTools namespace.
danielebarchiesi@0 34 if (!Drupal.CTools) {
danielebarchiesi@0 35 Drupal.CTools = {};
danielebarchiesi@0 36 }
danielebarchiesi@0 37
danielebarchiesi@0 38 /**
danielebarchiesi@0 39 * Object to store state.
danielebarchiesi@0 40 *
danielebarchiesi@0 41 * This object will remember the state of collapsible containers. The first
danielebarchiesi@0 42 * time a state is requested, it will check the cookie and set up the variable.
danielebarchiesi@0 43 * If a state has been changed, when the window is unloaded the state will be
danielebarchiesi@0 44 * saved.
danielebarchiesi@0 45 */
danielebarchiesi@0 46 Drupal.CTools.Collapsible = {
danielebarchiesi@0 47 state: {},
danielebarchiesi@0 48 stateLoaded: false,
danielebarchiesi@0 49 stateChanged: false,
danielebarchiesi@0 50 cookieString: 'ctools-collapsible-state=',
danielebarchiesi@0 51
danielebarchiesi@0 52 /**
danielebarchiesi@0 53 * Get the current collapsed state of a container.
danielebarchiesi@0 54 *
danielebarchiesi@0 55 * If set to 1, the container is open. If set to -1, the container is
danielebarchiesi@0 56 * collapsed. If unset the state is unknown, and the default state should
danielebarchiesi@0 57 * be used.
danielebarchiesi@0 58 */
danielebarchiesi@0 59 getState: function (id) {
danielebarchiesi@0 60 if (!this.stateLoaded) {
danielebarchiesi@0 61 this.loadCookie();
danielebarchiesi@0 62 }
danielebarchiesi@0 63
danielebarchiesi@0 64 return this.state[id];
danielebarchiesi@0 65 },
danielebarchiesi@0 66
danielebarchiesi@0 67 /**
danielebarchiesi@0 68 * Set the collapsed state of a container for subsequent page loads.
danielebarchiesi@0 69 *
danielebarchiesi@0 70 * Set the state to 1 for open, -1 for collapsed.
danielebarchiesi@0 71 */
danielebarchiesi@0 72 setState: function (id, state) {
danielebarchiesi@0 73 if (!this.stateLoaded) {
danielebarchiesi@0 74 this.loadCookie();
danielebarchiesi@0 75 }
danielebarchiesi@0 76
danielebarchiesi@0 77 this.state[id] = state;
danielebarchiesi@0 78
danielebarchiesi@0 79 if (!this.stateChanged) {
danielebarchiesi@0 80 this.stateChanged = true;
danielebarchiesi@0 81 $(window).unload(this.unload);
danielebarchiesi@0 82 }
danielebarchiesi@0 83 },
danielebarchiesi@0 84
danielebarchiesi@0 85 /**
danielebarchiesi@0 86 * Check the cookie and load the state variable.
danielebarchiesi@0 87 */
danielebarchiesi@0 88 loadCookie: function () {
danielebarchiesi@0 89 // If there is a previous instance of this cookie
danielebarchiesi@0 90 if (document.cookie.length > 0) {
danielebarchiesi@0 91 // Get the number of characters that have the list of values
danielebarchiesi@0 92 // from our string index.
danielebarchiesi@0 93 offset = document.cookie.indexOf(this.cookieString);
danielebarchiesi@0 94
danielebarchiesi@0 95 // If its positive, there is a list!
danielebarchiesi@0 96 if (offset != -1) {
danielebarchiesi@0 97 offset += this.cookieString.length;
danielebarchiesi@0 98 var end = document.cookie.indexOf(';', offset);
danielebarchiesi@0 99 if (end == -1) {
danielebarchiesi@0 100 end = document.cookie.length;
danielebarchiesi@0 101 }
danielebarchiesi@0 102
danielebarchiesi@0 103 // Get a list of all values that are saved on our string
danielebarchiesi@0 104 var cookie = unescape(document.cookie.substring(offset, end));
danielebarchiesi@0 105
danielebarchiesi@0 106 if (cookie != '') {
danielebarchiesi@0 107 var cookieList = cookie.split(',');
danielebarchiesi@0 108 for (var i = 0; i < cookieList.length; i++) {
danielebarchiesi@0 109 var info = cookieList[i].split(':');
danielebarchiesi@0 110 this.state[info[0]] = info[1];
danielebarchiesi@0 111 }
danielebarchiesi@0 112 }
danielebarchiesi@0 113 }
danielebarchiesi@0 114 }
danielebarchiesi@0 115
danielebarchiesi@0 116 this.stateLoaded = true;
danielebarchiesi@0 117 },
danielebarchiesi@0 118
danielebarchiesi@0 119 /**
danielebarchiesi@0 120 * Turn the state variable into a string and store it in the cookie.
danielebarchiesi@0 121 */
danielebarchiesi@0 122 storeCookie: function () {
danielebarchiesi@0 123 var cookie = '';
danielebarchiesi@0 124
danielebarchiesi@0 125 // Get a list of IDs, saparated by comma
danielebarchiesi@0 126 for (i in this.state) {
danielebarchiesi@0 127 if (cookie != '') {
danielebarchiesi@0 128 cookie += ',';
danielebarchiesi@0 129 }
danielebarchiesi@0 130 cookie += i + ':' + this.state[i];
danielebarchiesi@0 131 }
danielebarchiesi@0 132
danielebarchiesi@0 133 // Save this values on the cookie
danielebarchiesi@0 134 document.cookie = this.cookieString + escape(cookie) + ';path=/';
danielebarchiesi@0 135 },
danielebarchiesi@0 136
danielebarchiesi@0 137 /**
danielebarchiesi@0 138 * Respond to the unload event by storing the current state.
danielebarchiesi@0 139 */
danielebarchiesi@0 140 unload: function() {
danielebarchiesi@0 141 Drupal.CTools.Collapsible.storeCookie();
danielebarchiesi@0 142 }
danielebarchiesi@0 143 };
danielebarchiesi@0 144
danielebarchiesi@0 145 // Set up an array for callbacks.
danielebarchiesi@0 146 Drupal.CTools.CollapsibleCallbacks = [];
danielebarchiesi@0 147 Drupal.CTools.CollapsibleCallbacksAfterToggle = [];
danielebarchiesi@0 148
danielebarchiesi@0 149 /**
danielebarchiesi@0 150 * Bind collapsible behavior to a given container.
danielebarchiesi@0 151 */
danielebarchiesi@0 152 Drupal.CTools.bindCollapsible = function () {
danielebarchiesi@0 153 var $container = $(this);
danielebarchiesi@0 154
danielebarchiesi@0 155 // Allow the specification of the 'no container' class, which means the
danielebarchiesi@0 156 // handle and the container can be completely independent.
danielebarchiesi@0 157 if ($container.hasClass('ctools-no-container') && $container.attr('id')) {
danielebarchiesi@0 158 // In this case, the container *is* the handle and the content is found
danielebarchiesi@0 159 // by adding '-content' to the id. Obviously, an id is required.
danielebarchiesi@0 160 var handle = $container;
danielebarchiesi@0 161 var content = $('#' + $container.attr('id') + '-content');
danielebarchiesi@0 162 }
danielebarchiesi@0 163 else {
danielebarchiesi@0 164 var handle = $container.children('.ctools-collapsible-handle');
danielebarchiesi@0 165 var content = $container.children('div.ctools-collapsible-content');
danielebarchiesi@0 166 }
danielebarchiesi@0 167
danielebarchiesi@0 168 if (content.length) {
danielebarchiesi@0 169 // Create the toggle item and place it in front of the toggle.
danielebarchiesi@0 170 var toggle = $('<span class="ctools-toggle"></span>');
danielebarchiesi@0 171 handle.before(toggle);
danielebarchiesi@0 172
danielebarchiesi@0 173 // If the remember class is set, check to see if we have a remembered
danielebarchiesi@0 174 // state stored.
danielebarchiesi@0 175 if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
danielebarchiesi@0 176 var state = Drupal.CTools.Collapsible.getState($container.attr('id'));
danielebarchiesi@0 177 if (state == 1) {
danielebarchiesi@0 178 $container.removeClass('ctools-collapsed');
danielebarchiesi@0 179 }
danielebarchiesi@0 180 else if (state == -1) {
danielebarchiesi@0 181 $container.addClass('ctools-collapsed');
danielebarchiesi@0 182 }
danielebarchiesi@0 183 }
danielebarchiesi@0 184
danielebarchiesi@0 185 // If we should start collapsed, do so:
danielebarchiesi@0 186 if ($container.hasClass('ctools-collapsed')) {
danielebarchiesi@0 187 toggle.toggleClass('ctools-toggle-collapsed');
danielebarchiesi@0 188 content.hide();
danielebarchiesi@0 189 }
danielebarchiesi@0 190
danielebarchiesi@0 191 var afterToggle = function () {
danielebarchiesi@0 192 if (Drupal.CTools.CollapsibleCallbacksAfterToggle) {
danielebarchiesi@0 193 for (i in Drupal.CTools.CollapsibleCallbacksAfterToggle) {
danielebarchiesi@0 194 Drupal.CTools.CollapsibleCallbacksAfterToggle[i]($container, handle, content, toggle);
danielebarchiesi@0 195 }
danielebarchiesi@0 196 }
danielebarchiesi@0 197 }
danielebarchiesi@0 198
danielebarchiesi@0 199 var clickMe = function () {
danielebarchiesi@0 200 if (Drupal.CTools.CollapsibleCallbacks) {
danielebarchiesi@0 201 for (i in Drupal.CTools.CollapsibleCallbacks) {
danielebarchiesi@0 202 Drupal.CTools.CollapsibleCallbacks[i]($container, handle, content, toggle);
danielebarchiesi@0 203 }
danielebarchiesi@0 204 }
danielebarchiesi@0 205
danielebarchiesi@0 206 // If the container is a table element slideToggle does not do what
danielebarchiesi@0 207 // we want, so use toggle() instead.
danielebarchiesi@0 208 if ($container.is('table')) {
danielebarchiesi@0 209 content.toggle(0, afterToggle);
danielebarchiesi@0 210 }
danielebarchiesi@0 211 else {
danielebarchiesi@0 212 content.slideToggle(100, afterToggle);
danielebarchiesi@0 213 }
danielebarchiesi@0 214
danielebarchiesi@0 215 toggle.toggleClass('ctools-toggle-collapsed');
danielebarchiesi@0 216
danielebarchiesi@0 217 // If we're supposed to remember the state of this class, do so.
danielebarchiesi@0 218 if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
danielebarchiesi@0 219 var state = toggle.hasClass('ctools-toggle-collapsed') ? -1 : 1;
danielebarchiesi@0 220 Drupal.CTools.Collapsible.setState($container.attr('id'), state);
danielebarchiesi@0 221 }
danielebarchiesi@0 222
danielebarchiesi@0 223 return false;
danielebarchiesi@0 224 }
danielebarchiesi@0 225
danielebarchiesi@0 226 // Let both the toggle and the handle be clickable.
danielebarchiesi@0 227 toggle.click(clickMe);
danielebarchiesi@0 228 handle.click(clickMe);
danielebarchiesi@0 229 }
danielebarchiesi@0 230 };
danielebarchiesi@0 231
danielebarchiesi@0 232 /**
danielebarchiesi@0 233 * Support Drupal's 'behaviors' system for binding.
danielebarchiesi@0 234 */
danielebarchiesi@0 235 Drupal.behaviors.CToolsCollapsible = {
danielebarchiesi@0 236 attach: function(context) {
danielebarchiesi@0 237 $('.ctools-collapsible-container', context).once('ctools-collapsible', Drupal.CTools.bindCollapsible);
danielebarchiesi@0 238 }
danielebarchiesi@0 239 }
danielebarchiesi@0 240 })(jQuery);