Projet

Général

Profil

Paste
Télécharger (7,78 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ctools / js / collapsible-div.js @ 6e3ce7c2

1
/**
2
 * @file
3
 * Javascript required for a simple collapsible div.
4
 *
5
 * Creating a collapsible div with this doesn't take too much. There are
6
 * three classes necessary:
7
 *
8
 * - ctools-collapsible-container: This is the overall container that will be
9
 *   collapsible. This must be a div.
10
 * - ctools-collapsible-handle: This is the title area, and is what will be
11
 *   visible when it is collapsed. This can be any block element, such as div
12
 *   or h2.
13
 * - ctools-collapsible-content: This is the ocntent area and will only be
14
 *   visible when expanded. This must be a div.
15
 *
16
 * Adding 'ctools-collapsible-remember' to the container class will cause the
17
 * state of the container to be stored in a cookie, and remembered from page
18
 * load to page load. This will only work if the container has a unique ID, so
19
 * very carefully add IDs to your containers.
20
 *
21
 * If the class 'ctools-no-container' is placed on the container, the container
22
 * will be the handle. The content will be found by appending '-content' to the
23
 * id of the handle. The ctools-collapsible-handle and
24
 * ctools-collapsible-content classes will not be required in that case, and no
25
 * restrictions on what of data the container is are placed. Like
26
 * ctools-collapsible-remember this requires an id to eist.
27
 *
28
 * The content will be 'open' unless the container class has 'ctools-collapsed'
29
 * as a class, which will cause the container to draw collapsed.
30
 */
31

    
32
(function ($) {
33
  // All CTools tools begin with this if they need to use the CTools namespace.
34
  if (!Drupal.CTools) {
35
    Drupal.CTools = {};
36
  }
37

    
38
  /**
39
   * Object to store state.
40
   *
41
   * This object will remember the state of collapsible containers. The first
42
   * time a state is requested, it will check the cookie and set up the variable.
43
   * If a state has been changed, when the window is unloaded the state will be
44
   * saved.
45
   */
46
  Drupal.CTools.Collapsible = {
47
    state: {},
48
    stateLoaded: false,
49
    stateChanged: false,
50
    cookieString: 'ctools-collapsible-state=',
51

    
52
    /**
53
     * Get the current collapsed state of a container.
54
     *
55
     * If set to 1, the container is open. If set to -1, the container is
56
     * collapsed. If unset the state is unknown, and the default state should
57
     * be used.
58
     */
59
    getState: function (id) {
60
      if (!this.stateLoaded) {
61
        this.loadCookie();
62
      }
63

    
64
      return this.state[id];
65
    },
66

    
67
    /**
68
     * Set the collapsed state of a container for subsequent page loads.
69
     *
70
     * Set the state to 1 for open, -1 for collapsed.
71
     */
72
    setState: function (id, state) {
73
      if (!this.stateLoaded) {
74
        this.loadCookie();
75
      }
76

    
77
      this.state[id] = state;
78

    
79
      if (!this.stateChanged) {
80
        this.stateChanged = true;
81
        $(window).unload(this.unload);
82
      }
83
    },
84

    
85
    /**
86
     * Check the cookie and load the state variable.
87
     */
88
    loadCookie: function () {
89
      // If there is a previous instance of this cookie
90
      if (document.cookie.length > 0) {
91
        // Get the number of characters that have the list of values
92
        // from our string index.
93
        offset = document.cookie.indexOf(this.cookieString);
94

    
95
        // If its positive, there is a list!
96
        if (offset != -1) {
97
          offset += this.cookieString.length;
98
          var end = document.cookie.indexOf(';', offset);
99
          if (end == -1) {
100
            end = document.cookie.length;
101
          }
102

    
103
          // Get a list of all values that are saved on our string
104
          var cookie = unescape(document.cookie.substring(offset, end));
105

    
106
          if (cookie != '') {
107
            var cookieList = cookie.split(',');
108
            for (var i = 0; i < cookieList.length; i++) {
109
              var info = cookieList[i].split(':');
110
              this.state[info[0]] = info[1];
111
            }
112
          }
113
        }
114
      }
115

    
116
      this.stateLoaded = true;
117
    },
118

    
119
    /**
120
     * Turn the state variable into a string and store it in the cookie.
121
     */
122
    storeCookie: function () {
123
      var cookie = '';
124

    
125
      // Get a list of IDs, saparated by comma
126
      for (var i in this.state) {
127
        if (cookie != '') {
128
          cookie += ',';
129
        }
130
        cookie += i + ':' + this.state[i];
131
      }
132

    
133
      // Save this values on the cookie
134
      document.cookie = this.cookieString + escape(cookie) + ';path=/';
135
    },
136

    
137
    /**
138
     * Respond to the unload event by storing the current state.
139
     */
140
    unload: function() {
141
      Drupal.CTools.Collapsible.storeCookie();
142
    }
143
  };
144

    
145
  // Set up an array for callbacks.
146
  Drupal.CTools.CollapsibleCallbacks = [];
147
  Drupal.CTools.CollapsibleCallbacksAfterToggle = [];
148

    
149
  /**
150
   * Bind collapsible behavior to a given container.
151
   */
152
  Drupal.CTools.bindCollapsible = function () {
153
    var $container = $(this);
154

    
155
    // Allow the specification of the 'no container' class, which means the
156
    // handle and the container can be completely independent.
157
    if ($container.hasClass('ctools-no-container') && $container.attr('id')) {
158
      // In this case, the container *is* the handle and the content is found
159
      // by adding '-content' to the id. Obviously, an id is required.
160
      var handle = $container;
161
      var content = $('#' + $container.attr('id') + '-content');
162
    }
163
    else {
164
      var handle = $container.children('.ctools-collapsible-handle');
165
      var content = $container.children('div.ctools-collapsible-content');
166
    }
167

    
168
    if (content.length) {
169
      // Create the toggle item and place it in front of the toggle.
170
      var toggle = $('<span class="ctools-toggle"></span>');
171
      handle.before(toggle);
172

    
173
      // If the remember class is set, check to see if we have a remembered
174
      // state stored.
175
      if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
176
        var state = Drupal.CTools.Collapsible.getState($container.attr('id'));
177
        if (state == 1) {
178
          $container.removeClass('ctools-collapsed');
179
        }
180
        else if (state == -1) {
181
          $container.addClass('ctools-collapsed');
182
        }
183
      }
184

    
185
      // If we should start collapsed, do so:
186
      if ($container.hasClass('ctools-collapsed')) {
187
        toggle.toggleClass('ctools-toggle-collapsed');
188
        content.hide();
189
      }
190

    
191
      var afterToggle = function () {
192
        if (Drupal.CTools.CollapsibleCallbacksAfterToggle) {
193
          for (var i in Drupal.CTools.CollapsibleCallbacksAfterToggle) {
194
            Drupal.CTools.CollapsibleCallbacksAfterToggle[i]($container, handle, content, toggle);
195
          }
196
        }
197
      };
198

    
199
      var clickMe = function () {
200
        if (Drupal.CTools.CollapsibleCallbacks) {
201
          for (var i in Drupal.CTools.CollapsibleCallbacks) {
202
            Drupal.CTools.CollapsibleCallbacks[i]($container, handle, content, toggle);
203
          }
204
        }
205

    
206
        // If the container is a table element slideToggle does not do what
207
        // we want, so use toggle() instead.
208
        if ($container.is('table')) {
209
          content.toggle(0, afterToggle);
210
        }
211
        else {
212
          content.slideToggle(100, afterToggle);
213
        }
214

    
215
        $container.toggleClass('ctools-collapsed');
216
        toggle.toggleClass('ctools-toggle-collapsed');
217

    
218
        // If we're supposed to remember the state of this class, do so.
219
        if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
220
          var state = toggle.hasClass('ctools-toggle-collapsed') ? -1 : 1;
221
          Drupal.CTools.Collapsible.setState($container.attr('id'), state);
222
        }
223

    
224
        return false;
225
      };
226

    
227
      // Let both the toggle and the handle be clickable.
228
      toggle.click(clickMe);
229
      handle.click(clickMe);
230
    }
231
  };
232

    
233
  /**
234
   * Support Drupal's 'behaviors' system for binding.
235
   */
236
  Drupal.behaviors.CToolsCollapsible = {
237
    attach: function(context) {
238
      $('.ctools-collapsible-container', context).once('ctools-collapsible', Drupal.CTools.bindCollapsible);
239
    }
240
  };
241
})(jQuery);