/[drupal]/contributions/modules/dhtml_menu/dhtml_menu.js
ViewVC logotype

Contents of /contributions/modules/dhtml_menu/dhtml_menu.js

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.47 - (show annotations) (download) (as text)
Sun Oct 25 14:36:44 2009 UTC (4 weeks, 5 days ago) by arancaytar
Branch: MAIN
Branch point for: DRUPAL-6--4
Changes since 1.46: +5 -5 lines
File MIME type: text/javascript
#473356: Rename pseudo-child to clone everywhere, to make the meaning clearer.
1 // $Id: dhtml_menu.js,v 1.46 2009/10/25 14:32:36 arancaytar Exp $
2
3 /**
4 * @file dhtml_menu.js
5 * The Javascript code for DHTML Menu
6 */
7
8
9 (function($) {
10 Drupal.dhtmlMenu = {};
11 Drupal.dhtmlMenu.animation = {show:{}, hide:{}, count:0};
12
13 /**
14 * Initialize the module's JS functions
15 */
16 Drupal.behaviors.dhtmlMenu = {
17 attach: function() {
18 var settings = Drupal.settings.dhtmlMenu;
19
20 // Initialize the animation effects from the settings.
21 for (i in settings.animation.effects) {
22 if (settings.animation.effects[i]) {
23 Drupal.dhtmlMenu.animation.show[i] = 'show';
24 Drupal.dhtmlMenu.animation.hide[i] = 'hide';
25 Drupal.dhtmlMenu.animation.count++;
26 }
27 }
28
29 // Sanitize by removing "expanded" on menus already marked "collapsed".
30 $('li.dhtml-menu.collapsed.expanded').removeClass('expanded');
31
32 /* Relevant only on "open-only" menus:
33 * The links of expanded items should be marked for emphasis.
34 */
35 if (settings.nav == 'open') {
36 $('li.dhtml-menu.expanded').addClass('dhtml-menu-open');
37 }
38
39 /* Relevant only when hovering:
40 *
41 * If a context menu is opened (as most users do when opening links in a
42 * new tab), the mouseleave event will be triggered. Although the context
43 * menu still works, having the menu close underneath it is confusing.
44 *
45 * This code will "freeze" the menu's collapse if the body is left
46 * (which happens when a context menu opens), and only release it when the cursor
47 * reenters the menu.
48 *
49 * Note that due to the order in which events are called,
50 * the hovering collapse must work asynchronously so
51 * this event is triggered before the collapse.
52 */
53 else if (settings.nav == 'hover') {
54 var freeze = false;
55 $('ul.menu').mouseenter(function() {freeze = false});
56 $('body').mouseleave(function() {freeze = true});
57 }
58
59 /* Relevant only on bullet-icon expansion:
60 * Create the markup for the bullet overlay, and the amount to shift it to the right in RTL mode.
61 */
62 else if (settings.nav == 'bullet') {
63 var bullet = $('<a href="#" class="dhtml-menu-icon"></a>');
64 var rtl = $('html').attr('dir') == 'rtl' ? Math.ceil($('.menu li').css('margin-right').replace('px', '')) + 1 : 0;
65 }
66
67 /* Relevant only when adding cloned links:
68 * Create the markup for the cloned list item container.
69 */
70 else if (settings.nav == 'clone') {
71 // Note: a single long class is used here to avoid matching the .dhtml-menu.leaf selector later on.
72 var cloned = $('<li class="leaf dhtml-menu-cloned-leaf"></li>');
73 }
74
75 /* Add jQuery effects and listeners to all menu items. */
76 $('ul.menu li.dhtml-menu:not(.leaf)').each(function() {
77 var li = $(this);
78 var link = $(this).find('a:first');
79 var ul = $(this).find('ul:first');
80
81 // Only work on menus with an actual sub-menu.
82 if (link.length && ul.length) {
83 /* When using cloned items:
84 * - Clone the menu link and mark it as a clone.
85 */
86 if (settings.nav == 'clone') {
87 link.clone().prependTo(ul).wrap(cloned);
88 }
89
90 /* When using double-click:
91 * - Add a dblclick event handler that allows the normal link action to complete.
92 */
93 else if (settings.nav == 'doubleclick') {
94 link.dblclick(function(e) {
95 return true;
96 });
97 }
98
99 /* When using bullet expansion:
100 * - Change the icon to a folder image
101 * - Add the clickable overlay and its handler
102 * - In RTL mode, shift the overlay to the right of the text.
103 * - @TODO: Explore whether "float:right" in dhtml_menu-rtl.css could solve this.
104 */
105 else if (settings.nav == 'bullet') {
106 li.addClass('dhtml-folder');
107 var b = bullet.clone().prependTo(link).click(function(e) {
108 Drupal.dhtmlMenu.toggleMenu(li, link, ul);
109 if (settings.effects.remember) {
110 Drupal.dhtmlMenu.cookieSet();
111 }
112 return false;
113 });
114
115 // When using RTL, each overlay must be shifted to the other side of the link text, individually.
116 if (rtl) {
117 // Shift the overlay right by the width of the text and the distance between text and icon.
118 b.css('right', '-' + (Math.ceil(link.css('width').replace('px', '')) + rtl) + 'px');
119 }
120 }
121
122 /* When using hover expansion:
123 * - Add mouse-hovering events.
124 */
125 else if (settings.nav == 'hover') {
126 link.mouseenter(function(e) {
127 Drupal.dhtmlMenu.switchMenu(li, link, ul, true);
128 });
129 li.mouseleave(function(e) {
130 // Only collapse the menu if it was initially collapsed.
131 if (li.hasClass('start-collapsed')) {
132 /* As explained earlier, this event fires before the body event.
133 * We need to wait to make sure that the user isn't browsing a
134 * context menu right now, in which case the menu isn't collapsed.
135 */
136 setTimeout(function() {
137 if (!freeze) {
138 Drupal.dhtmlMenu.switchMenu(li, link, ul, false);
139 }
140 }, 10);
141 }
142 });
143 }
144
145 /* When using menus that cannot collapse:
146 * Toggle the menu normally, but only if the menu is closed.
147 */
148 else if (settings.nav == 'open') {
149 link.click(function(e) {
150 // Don't collapse expanded menus.
151 if (li.hasClass('expanded')) {
152 return true;
153 }
154 Drupal.dhtmlMenu.toggleMenu(li, link, ul);
155 $('.dhtml-menu-open').removeClass('dhtml-menu-open');
156 $('li.dhtml-menu.expanded').addClass('dhtml-menu-open');
157 return false;
158 });
159 }
160
161 // These three options make links simply toggle when clicked.
162 if (settings.nav == 'clone' || settings.nav == 'doubleclick' || settings.nav == 'none') {
163 link.click(function(e) {
164 Drupal.dhtmlMenu.toggleMenu(li, link, ul);
165 if (settings.effects.remember) {
166 Drupal.dhtmlMenu.cookieSet();
167 }
168 return false;
169 });
170 }
171 }
172 });
173
174 // When using LTR, all icons can be shifted as one, as the text width is not relevant.
175 if (settings.nav == 'bullet' && !rtl) {
176 // Shift overlay to the left by the width of the icon and the distance between icon and text.
177 var shift = '-' + (Math.ceil(($('.menu li').css('margin-left').replace('px', ''))) + 16) + 'px';
178 // Shift the overlay using a negative left-hand offset, and the text using a negative right-hand margin.
179 $('.dhtml-menu-icon').css('left', shift).css('margin-right', shift);
180 }
181 }
182 }
183
184 /**
185 * Toggles the menu's state between open and closed.
186 *
187 * @param li
188 * Object. The <li> element that will be expanded or collapsed.
189 * @param link
190 * Object. The <a> element representing the menu link anchor.
191 * @param ul
192 * Object. The <ul> element containing the sub-items.
193 */
194 Drupal.dhtmlMenu.toggleMenu = function(li, link, ul) {
195 // Make it open if closed, close if open.
196 Drupal.dhtmlMenu.switchMenu(li, link, ul, !li.hasClass('expanded'));
197 }
198
199 /**
200 * Switches the menu's state to a defined value.
201 * This function does nothing if the menu is in the target state already.
202 *
203 * @param li
204 * Object. The <li> element that will be expanded or collapsed.
205 * @param link
206 * Object. The <a> element representing the menu link anchor.
207 * @param ul
208 * Object. The <ul> element containing the sub-items.
209 */
210 Drupal.dhtmlMenu.switchMenu = function(li, link, ul, open) {
211 // No need for switching. Menu is already in desired state.
212 if (open == li.hasClass('expanded')) {
213 return;
214 }
215
216 var effects = Drupal.settings.dhtmlMenu.effects;
217
218 if (open) {
219 Drupal.dhtmlMenu.animate(ul, 'show');
220 li.removeClass('collapsed').addClass('expanded');
221
222 // If the siblings effect is on, close all sibling menus.
223 if (effects.siblings != 'none') {
224 var id = link.attr('id');
225 /* Siblings are all open menus that are neither parents nor children of this menu.
226 * First, mark this item's children for exclusion.
227 */
228 li.find('li').addClass('own-children-temp');
229
230 // If the relativity option is on, select only the siblings that have the same root
231 if (effects.siblings == 'close-same-tree') {
232 var root = li.parent();
233 }
234 else {
235 var root = $('ul.menu');
236 }
237 var siblings = root.find('li.expanded').not('.own-children-temp').not(':has(#' + id + ')');
238
239 // If children should not get closed automatically...
240 if (effects.children == 'none') {
241 // Remove items that are currently hidden from view (do not close these).
242 $('li.collapsed li.expanded').addClass('sibling-children-temp');
243 // Only close the top-most open sibling, not its children.
244 siblings.find('li.expanded').addClass('sibling-children-temp');
245 siblings = $(siblings).not('.sibling-children-temp');
246 }
247
248 // The temp classes can now be removed.
249 $('.own-children-temp, .sibling-children-temp')
250 .removeClass('own-children-temp')
251 .removeClass('sibling-children-temp');
252
253 Drupal.dhtmlMenu.animate(siblings.find('ul:first'), 'hide');
254 siblings.removeClass('expanded').addClass('collapsed');
255 }
256 }
257 else {
258 Drupal.dhtmlMenu.animate(ul, 'hide');
259 li.removeClass('expanded').addClass('collapsed');
260
261 // If children are closed automatically, find and close them now.
262 if (effects.children == 'close-children') {
263 // If a sub-menu closes in the forest and nobody sees it, is animation a waste of performance? Yes.
264 li.find('li.expanded')
265 .removeClass('expanded').addClass('collapsed')
266 .find('ul:first').css('display', 'none');
267 }
268 }
269 }
270
271 /**
272 * Animate a specific block element using the configured DHTML effects.
273 *
274 * @param element
275 * The element to be animated. DHTML Menu only animates <ul> elements,
276 * but this could in theory be any block (not inline) element.
277 *
278 * @param action
279 * One of either 'show' or 'hide'.
280 */
281 Drupal.dhtmlMenu.animate = function(element, action) {
282 var effects = Drupal.dhtmlMenu.animation;
283 var speed = Drupal.settings.dhtmlMenu.animation.speed;
284
285 if (effects.count) {
286 element.animate(effects[action], speed * 1);
287 }
288 else {
289 element.css('display', action == 'show' ? 'block' : 'none');
290 }
291 }
292
293 /**
294 * Saves the dhtml_menu cookie.
295 */
296 Drupal.dhtmlMenu.cookieSet = function() {
297 var expanded = new Array();
298 $('li.expanded').each(function() {
299 expanded.push($(this).children('a:first').attr('id'));
300 });
301 document.cookie = 'dhtml_menu=' + expanded.join(',') + ';path=/';
302 }
303
304 })(jQuery);
305

  ViewVC Help
Powered by ViewVC 1.1.2