Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 373
- Log:
Initial import of Radiant 0.9.1, which is now packaged as a gem. This is an
import of the tagged 0.9.1 source checked out from GitHub, which isn't quite
the same as the gem distribution - but it doesn't seem to be available in an
archived form and the installed gem already has modifications, so this is
the closest I can get.
- Author:
- rool
- Date:
- Mon Mar 21 13:40:05 +0000 2011
- Size:
- 15287 Bytes
1 | /* |
2 | * toggle.js |
3 | * |
4 | * dependencies: prototype.js, lowpro.js, effect.js |
5 | * |
6 | * -------------------------------------------------------------------------- |
7 | * |
8 | * A LowPro and Prototype-based library with a collection of behaviors for |
9 | * unobtrusively toggling the visibility of other elements via links, |
10 | * checkboxes, radio buttons, and selects. |
11 | * |
12 | * To use you will need to install the following LowPro behaviors. If you are |
13 | * using Rails, put this in "application.js": |
14 | * |
15 | * Event.addBehavior({ |
16 | * 'a.toggle': Toggle.LinkBehavior(), |
17 | * 'input.checkbox.toggle': Toggle.CheckboxBehavior(), |
18 | * 'div.radio_group.toggle': Toggle.RadioGroupBehavior(), |
19 | * 'select.toggle': Toggle.SelectBehavior() |
20 | * }); |
21 | * |
22 | * Once the hooks are installed correctly, you should add a "rel" attribute |
23 | * to each element that you want to use as a toggle trigger. Set the value |
24 | * of the "rel" attribute to "toggle[id]" where id is equal to the ID of |
25 | * the element that you want to toggle. You can toggle multiple elements by |
26 | * separating the IDs with commas (like this: "toggle[id1,id2,id3]"). |
27 | * |
28 | * For example, a link with a class of "toggle": |
29 | * |
30 | * <a class="toggle" href="#more" rel="toggle[more]">More</a> |
31 | * |
32 | * will become a trigger for a div with an ID of "more". Checkboxes work in |
33 | * the exact same manner. To use with a group of radio buttons, make sure |
34 | * that all of the radio buttons are inside of a div with a class of |
35 | * "radio_group toggle". Then set the "rel" attribute on each radio button |
36 | * that should act as a toggle trigger. Selects work in a similar manner, |
37 | * but the "rel" attribute should be set on each option element that should |
38 | * toggle the visibility of an element or array of elements. |
39 | * |
40 | * Each of the included LowPro behaviors can be customized in various ways. |
41 | * Check out the inline documentation for detailed usage information. |
42 | * |
43 | * Project Homepage: http://github.com/fivepointssolutions/togglejs |
44 | * |
45 | * -------------------------------------------------------------------------- |
46 | * |
47 | * Copyright (c) 2007-2010, Five Points Solutions, Inc. |
48 | * Copyright (c) 2010, John W. Long |
49 | * |
50 | * Permission is hereby granted, free of charge, to any person obtaining a |
51 | * copy of this software and associated documentation files (the "Software"), |
52 | * to deal in the Software without restriction, including without limitation |
53 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
54 | * and/or sell copies of the Software, and to permit persons to whom the |
55 | * Software is furnished to do so, subject to the following conditions: |
56 | * |
57 | * The above copyright notice and this permission notice shall be included in |
58 | * all copies or substantial portions of the Software. |
59 | * |
60 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
61 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
62 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
63 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
64 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
65 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
66 | * DEALINGS IN THE SOFTWARE. |
67 | * |
68 | */ |
69 | |
70 | var Toggle = { |
71 | |
72 | DefaultEffect: 'slide', |
73 | DefaultEffectDuration: 0.25, |
74 | |
75 | EffectPairs: { |
76 | 'slide' : ['SlideDown','SlideUp'], |
77 | 'blind' : ['BlindDown','BlindUp'], |
78 | 'appear': ['Appear','Fade'] |
79 | }, |
80 | |
81 | /** |
82 | * Toggle.extractAnchor(url) -> String |
83 | * |
84 | * Utility function. Returns everything after the first "#" character in a |
85 | * string. Used to extract the anchor from a URL. |
86 | **/ |
87 | extractAnchor: function(url) { |
88 | var matches = String(url).match(/\#(.+)$/); |
89 | if (matches) return matches[1]; |
90 | }, |
91 | |
92 | /** |
93 | * Toggle.extractToggleObjects(string) -> Array |
94 | * |
95 | * Utility function. Returns the associated toggle elements in a string. For |
96 | * string "toggle[one,two,three]" it will return the elements with IDs of |
97 | * "one", "two", and "three". |
98 | **/ |
99 | extractToggleObjects: function(string) { |
100 | var matches = String(string).match(/^toggle\[(.+)\]$/); |
101 | if (matches) { |
102 | var ids = matches[1].split(','); |
103 | var elements = []; |
104 | ids.each(function(id) { elements.push($(id)) }); |
105 | return elements; |
106 | } else { |
107 | return []; |
108 | } |
109 | }, |
110 | |
111 | /** |
112 | * Toggle.toggle(elements, effect, options) |
113 | * |
114 | * Utility function. Toggles an element or array of elements with effect |
115 | * and options. Similar to `Effect.toggle()`, but works with multiple |
116 | * elements and also supports setting effect to "none". |
117 | * |
118 | * Parameters |
119 | * - elements: An element or array of elements to toggle |
120 | * - effect: This option specifies the effect that should be used when |
121 | * toggling. The default is "slide", but it can also be set to |
122 | * "blind", "appear", or "none". |
123 | * - options: The standard Effect options hash with the addition of |
124 | * beforeToggle and afterToggle events. |
125 | **/ |
126 | toggle: function(elements, effect, options) { |
127 | var elements = $A([elements]).flatten(); |
128 | var effect = (effect || Toggle.DefaultEffect).toLowerCase(); |
129 | var options = options || {}; |
130 | |
131 | if (effect == 'none') { |
132 | if (options.beforeStart) options.beforeStart(); |
133 | elements.invoke("toggle"); |
134 | if (options.afterFinish) options.afterFinish(); |
135 | } else { |
136 | options.duration = options.duration || Toggle.DefaultEffectDuration; |
137 | |
138 | var effects = elements.map(function(e) { |
139 | var element = $(e); |
140 | var inOrOut = element.visible() ? 1 : 0; |
141 | var name = Toggle.EffectPairs[effect][inOrOut]; |
142 | return new Effect[name](element, { sync: true }); |
143 | }); |
144 | |
145 | new Effect.Parallel(effects, options); |
146 | } |
147 | }, |
148 | |
149 | /** |
150 | * Toggle.show(elements, effect, options) |
151 | * |
152 | * Utility function. Shows an element or array of elements with effect |
153 | * and options. |
154 | **/ |
155 | show: function(elements, effect, options) { |
156 | var elements = $([elements]).flatten(); |
157 | elements = elements.map(function(element) { return $(element) }); |
158 | elements = elements.reject(function(element) { return element.visible() }); |
159 | Toggle.toggle(elements, effect, options); |
160 | }, |
161 | |
162 | /** |
163 | * Toggle.hide(elements, effect, options) |
164 | * |
165 | * Utility function. Hides an element or array of elements with effect |
166 | * and options. |
167 | **/ |
168 | hide: function(elements, effect, options) { |
169 | var elements = $([elements]).flatten(); |
170 | elements = elements.map(function(element) { return $(element) }); |
171 | elements = elements.reject(function(element) { return !element.visible() }); |
172 | Toggle.toggle(elements, effect, options); |
173 | }, |
174 | |
175 | /** |
176 | * Toggle.wrapElement(element) |
177 | * |
178 | * Utility function. Wraps element with a div of class "toggle_wrapper" |
179 | * unless one already exists. Returns the "toggle_wrapper" for given |
180 | * element. This is necessary because effects only work properly on |
181 | * elements that do not have padding, borders, or margin. |
182 | **/ |
183 | wrapElement: function(element) { |
184 | var element = $(element); |
185 | var parent = $(element.parentNode); |
186 | if (parent.hasClassName('toggle_wrapper')) { |
187 | return parent; |
188 | } else { |
189 | return element.wrap($div({'class': 'toggle_wrapper', 'style': 'display: none'})); |
190 | } |
191 | } |
192 | }; |
193 | |
194 | /** |
195 | * class Toggle.LinkBehavior < Behavior |
196 | * |
197 | * Allows a link to toggle the display of another element or array of |
198 | * elements on and off. Just set the <tt>rel</tt> attribute to |
199 | * "toggle[id1,id2,...]" on the link and the href of the link to the |
200 | * ID of the first element ("#id1"). |
201 | * |
202 | * Options |
203 | * - effect: This option specifies the effect that should be used when |
204 | * toggling. The default is "slide", but it can also be set to |
205 | * "blind", "appear", or "none". |
206 | * - onLoad: Called after the behavior is initialized. The function is |
207 | * automatically bound to the behavior (so "this" referes to the |
208 | * behavior). |
209 | * - beforeToggle: Called after the link is clicked, but before the effect is |
210 | * started. The link is passed as the first parameter and the |
211 | * function is automatically bound to the behavior (so "this" |
212 | * refers to the behavior). |
213 | * - afterToggle: Called after the effect is complete. The link is passed as |
214 | * the first parameter and the function is automatically bound |
215 | * to the behavior (so "this" refers to the behavior). |
216 | **/ |
217 | Toggle.LinkBehavior = Behavior.create({ |
218 | initialize: function(options) { |
219 | var options = options || {}; |
220 | |
221 | this.effect = options.effect || Toggle.DefaultEffect; |
222 | |
223 | this.onLoad = options.onLoad || Prototype.emptyFunction; |
224 | this.onLoad.bind(this); |
225 | |
226 | this.beforeToggle = options.beforeToggle || Prototype.emptyFunction; |
227 | this.beforeToggle.bind(this); |
228 | |
229 | this.afterToggle = options.afterToggle || Prototype.emptyFunction; |
230 | this.afterToggle.bind(this); |
231 | |
232 | var elements = Toggle.extractToggleObjects(this.element.readAttribute('rel')); |
233 | this.toggleWrappers = elements.map(function(e) { return Toggle.wrapElement(e) }); |
234 | |
235 | this.toggleID = Toggle.extractAnchor(this.element.href); |
236 | this.element.behavior = this; // a bit of a hack |
237 | Toggle.addLink(this.toggleID, this.element); |
238 | |
239 | this.onLoad(this.element); |
240 | }, |
241 | |
242 | onclick: function() { |
243 | this.toggle(); |
244 | return false; |
245 | }, |
246 | |
247 | toggle: function() { |
248 | Toggle.toggle( |
249 | this.toggleWrappers, |
250 | this.effect, |
251 | { |
252 | beforeStart: function() { this.beforeToggle(this.element) }.bind(this), |
253 | afterFinish: function() { this.afterToggle(this.element) }.bind(this) |
254 | } |
255 | ); |
256 | } |
257 | }); |
258 | Toggle.links = {}; |
259 | Toggle.addLink = function(id, element) { |
260 | this.links[id] = this.links[id] || $A(); |
261 | this.links[id].push(element); |
262 | }; |
263 | |
264 | |
265 | // Automatically toggle associated element if anchor is equal to the ID of the |
266 | // link's associated element. |
267 | Event.observe(window, 'dom:loaded', function() { |
268 | var anchor = Toggle.extractAnchor(window.location); |
269 | var links = Toggle.links[anchor]; |
270 | if (links) { |
271 | var behavior = links.first().behavior; |
272 | behavior.onclick(); |
273 | } |
274 | }); |
275 | |
276 | /** |
277 | * class Toggle.CheckboxBehavior < Behavior |
278 | * |
279 | * Allows a the selection of a checkbox to toggle an element or group of |
280 | * elements on and off. Just set the `rel` attribute to "toggle[id1,id2,...]" |
281 | * on the checkbox. |
282 | * |
283 | * Options |
284 | * - invert: When set to true the associated element is hidden when checked. |
285 | * - effect: This option specifies the effect that should be used when |
286 | * toggling. The default is "slide", but it can also be set to |
287 | * "blind", "appear", or "none". |
288 | **/ |
289 | Toggle.CheckboxBehavior = Behavior.create({ |
290 | initialize: function(options) { |
291 | var options = options || {}; |
292 | this.invert = options.invert; |
293 | |
294 | var elements = Toggle.extractToggleObjects(this.element.readAttribute('rel')); |
295 | this.toggleWrappers = elements.map(function(e) { return Toggle.wrapElement(e) }); |
296 | |
297 | this.effect = 'none'; |
298 | this.toggle(); |
299 | |
300 | this.effect = options.effect || Toggle.DefaultEffect; |
301 | }, |
302 | |
303 | onclick: function(event) { |
304 | this.toggle(); |
305 | }, |
306 | |
307 | toggle: function() { |
308 | var method, formElementMethod; |
309 | |
310 | if (this.invert) { |
311 | method = this.element.checked ? 'hide' : 'show'; |
312 | formElementMethod = this.element.checked ? 'disable' : 'enable'; |
313 | } else { |
314 | method = this.element.checked ? 'show' : 'hide'; |
315 | formElementMethod = this.element.checked ? 'enable' : 'disable'; |
316 | } |
317 | |
318 | Toggle[method](this.toggleWrappers, this.effect); |
319 | |
320 | // Disable/enable form elements based on whether the container is |
321 | // visible or not. |
322 | this.toggleWrappers.each(function(wrapper) { |
323 | Form.getElements(wrapper).invoke(formElementMethod); |
324 | }); |
325 | } |
326 | }); |
327 | |
328 | /** |
329 | * class Toggle.RadioGroupBehavior < Behavior |
330 | * |
331 | * Allows you to toggle elements based on the selection of a group of radio |
332 | * buttons. Just set the <tt>rel</tt> attribute to "toggle[id1,id2,...]" on |
333 | * each radio button. Radio buttons must be grouped inside a containing |
334 | * element to which the behavior is applied. |
335 | * |
336 | * Options |
337 | * - effect: This option specifies the effect that should be used when |
338 | * toggling. The default is "slide", but it can also be set to |
339 | * "blind", "appear", or "none". |
340 | **/ |
341 | Toggle.RadioGroupBehavior = Behavior.create({ |
342 | initialize: function(options) { |
343 | var options = options || {}; |
344 | |
345 | this.radioButtons = this.element.select('input[type=radio]'); |
346 | |
347 | this.toggleWrapperIDs = $A(); |
348 | this.toggleWrapperIDsFor = {}; |
349 | |
350 | this.radioButtons.each(function(radioButton) { |
351 | var elements = Toggle.extractToggleObjects(radioButton.readAttribute('rel')) |
352 | var ids = elements.invoke('identify'); |
353 | var wrapperIDs = elements.map(function(e) { return Toggle.wrapElement(e) }).invoke('identify'); |
354 | this.toggleWrapperIDsFor[radioButton.identify()] = wrapperIDs; |
355 | this.toggleWrapperIDs.push(wrapperIDs); |
356 | radioButton.observe('click', this.onRadioButtonClick.bind(this)); |
357 | }.bind(this)); |
358 | |
359 | this.toggleWrapperIDs = this.toggleWrapperIDs.flatten().uniq() |
360 | |
361 | this.effect = "none"; |
362 | this.toggle(); |
363 | |
364 | this.effect = options.effect || Toggle.DefaultEffect; |
365 | }, |
366 | |
367 | onRadioButtonClick: function(event) { |
368 | this.toggle(); |
369 | }, |
370 | |
371 | toggle: function() { |
372 | var group = this.element; |
373 | var radioButton = this.radioButtons.find(function(b) { return b.checked }); |
374 | var wrapperIDs = this.toggleWrapperIDsFor[radioButton.identify()]; |
375 | var partitioned = this.toggleWrapperIDs.partition(function(id) { return wrapperIDs.include(id) }); |
376 | Toggle.show(partitioned[0], this.effect); |
377 | Toggle.hide(partitioned[1], this.effect); |
378 | } |
379 | }); |
380 | |
381 | |
382 | /** |
383 | * class Toggle.SelectBehavior < Behavior |
384 | * |
385 | * Allows you to toggle elements based on the selection of a combo box. Just |
386 | * set the <tt>rel</tt> attribute to "toggle[id1,id2,...]" on the each select |
387 | * option. |
388 | * |
389 | * Options |
390 | * - effect: This option specifies the effect that should be used when |
391 | * toggling. The default is "slide", but it can also be set to |
392 | * "blind", "appear", or "none". |
393 | **/ |
394 | Toggle.SelectBehavior = Behavior.create({ |
395 | initialize: function(options) { |
396 | var options = options || {}; |
397 | |
398 | var optionElements = this.element.select('option'); |
399 | |
400 | this.toggleWrapperIDs = $A(); |
401 | this.toggleWrapperIDsFor = {}; |
402 | |
403 | optionElements.each(function(optionElement) { |
404 | var elements = Toggle.extractToggleObjects(optionElement.readAttribute('rel')) |
405 | var wrapperIDs = elements.map(function(e) { return Toggle.wrapElement(e) }).invoke('identify'); |
406 | this.toggleWrapperIDsFor[optionElement.identify()] = wrapperIDs; |
407 | this.toggleWrapperIDs.push(wrapperIDs); |
408 | }.bind(this)); |
409 | |
410 | this.toggleWrapperIDs = this.toggleWrapperIDs.flatten().uniq() |
411 | |
412 | this.effect = "none"; |
413 | this.toggle(); |
414 | |
415 | this.effect = options.effect || Toggle.DefaultEffect; |
416 | }, |
417 | |
418 | onchange: function(event) { |
419 | this.toggle(); |
420 | }, |
421 | |
422 | toggle: function() { |
423 | var combo = this.element; |
424 | var option = $(combo.options[combo.selectedIndex]); |
425 | var wrapperIDs = this.toggleWrapperIDsFor[option.identify()]; |
426 | var partitioned = this.toggleWrapperIDs.partition(function(id) { return wrapperIDs.include(id) }); |
427 | Toggle.show(partitioned[0], this.effect); |
428 | Toggle.hide(partitioned[1], this.effect); |
429 | } |
430 | }); |