root / drupal7 / modules / overlay / overlay-parent.js @ b75b6b8b
1 | 85ad3d82 | Assos Assos | /**
|
---|---|---|---|
2 | * @file
|
||
3 | * Attaches the behaviors for the Overlay parent pages.
|
||
4 | */
|
||
5 | |||
6 | (function ($) { |
||
7 | |||
8 | /**
|
||
9 | * Open the overlay, or load content into it, when an admin link is clicked.
|
||
10 | */
|
||
11 | Drupal.behaviors.overlayParent = { |
||
12 | attach: function (context, settings) { |
||
13 | if (Drupal.overlay.isOpen) {
|
||
14 | Drupal.overlay.makeDocumentUntabbable(context); |
||
15 | } |
||
16 | |||
17 | if (this.processed) { |
||
18 | return;
|
||
19 | } |
||
20 | this.processed = true; |
||
21 | |||
22 | $(window)
|
||
23 | // When the hash (URL fragment) changes, open the overlay if needed.
|
||
24 | .bind('hashchange.drupal-overlay', $.proxy(Drupal.overlay, 'eventhandlerOperateByURLFragment')) |
||
25 | // Trigger the hashchange handler once, after the page is loaded, so that
|
||
26 | // permalinks open the overlay.
|
||
27 | .triggerHandler('hashchange.drupal-overlay');
|
||
28 | |||
29 | $(document)
|
||
30 | // Instead of binding a click event handler to every link we bind one to
|
||
31 | // the document and only handle events that bubble up. This allows other
|
||
32 | // scripts to bind their own handlers to links and also to prevent
|
||
33 | // overlay's handling.
|
||
34 | .bind('click.drupal-overlay mouseup.drupal-overlay', $.proxy(Drupal.overlay, 'eventhandlerOverrideLink')); |
||
35 | } |
||
36 | }; |
||
37 | |||
38 | /**
|
||
39 | * Overlay object for parent windows.
|
||
40 | *
|
||
41 | * Events
|
||
42 | * Overlay triggers a number of events that can be used by other scripts.
|
||
43 | * - drupalOverlayOpen: This event is triggered when the overlay is opened.
|
||
44 | * - drupalOverlayBeforeClose: This event is triggered when the overlay attempts
|
||
45 | * to close. If an event handler returns false, the close will be prevented.
|
||
46 | * - drupalOverlayClose: This event is triggered when the overlay is closed.
|
||
47 | * - drupalOverlayBeforeLoad: This event is triggered right before a new URL
|
||
48 | * is loaded into the overlay.
|
||
49 | * - drupalOverlayReady: This event is triggered when the DOM of the overlay
|
||
50 | * child document is fully loaded.
|
||
51 | * - drupalOverlayLoad: This event is triggered when the overlay is finished
|
||
52 | * loading.
|
||
53 | * - drupalOverlayResize: This event is triggered when the overlay is being
|
||
54 | * resized to match the parent window.
|
||
55 | */
|
||
56 | Drupal.overlay = Drupal.overlay || { |
||
57 | isOpen: false, |
||
58 | isOpening: false, |
||
59 | isClosing: false, |
||
60 | isLoading: false |
||
61 | }; |
||
62 | |||
63 | Drupal.overlay.prototype = {}; |
||
64 | |||
65 | /**
|
||
66 | * Open the overlay.
|
||
67 | *
|
||
68 | * @param url
|
||
69 | * The URL of the page to open in the overlay.
|
||
70 | *
|
||
71 | * @return
|
||
72 | * TRUE if the overlay was opened, FALSE otherwise.
|
||
73 | */
|
||
74 | Drupal.overlay.open = function (url) { |
||
75 | // Just one overlay is allowed.
|
||
76 | if (this.isOpen || this.isOpening) { |
||
77 | return this.load(url); |
||
78 | } |
||
79 | this.isOpening = true; |
||
80 | // Store the original document title.
|
||
81 | this.originalTitle = document.title;
|
||
82 | |||
83 | // Create the dialog and related DOM elements.
|
||
84 | this.create();
|
||
85 | |||
86 | this.isOpening = false; |
||
87 | this.isOpen = true; |
||
88 | $(document.documentElement).addClass('overlay-open'); |
||
89 | this.makeDocumentUntabbable();
|
||
90 | |||
91 | // Allow other scripts to respond to this event.
|
||
92 | $(document).trigger('drupalOverlayOpen'); |
||
93 | |||
94 | return this.load(url); |
||
95 | }; |
||
96 | |||
97 | /**
|
||
98 | * Create the underlying markup and behaviors for the overlay.
|
||
99 | */
|
||
100 | Drupal.overlay.create = function () { |
||
101 | this.$container = $(Drupal.theme('overlayContainer')) |
||
102 | .appendTo(document.body); |
||
103 | |||
104 | // Overlay uses transparent iframes that cover the full parent window.
|
||
105 | // When the overlay is open the scrollbar of the parent window is hidden.
|
||
106 | // Because some browsers show a white iframe background for a short moment
|
||
107 | // while loading a page into an iframe, overlay uses two iframes. By loading
|
||
108 | // the page in a hidden (inactive) iframe the user doesn't see the white
|
||
109 | // background. When the page is loaded the active and inactive iframes
|
||
110 | // are switched.
|
||
111 | this.activeFrame = this.$iframeA = $(Drupal.theme('overlayElement')) |
||
112 | .appendTo(this.$container); |
||
113 | |||
114 | this.inactiveFrame = this.$iframeB = $(Drupal.theme('overlayElement')) |
||
115 | .appendTo(this.$container); |
||
116 | |||
117 | this.$iframeA.bind('load.drupal-overlay', { self: this.$iframeA[0], sibling: this.$iframeB }, $.proxy(this, 'loadChild')); |
||
118 | this.$iframeB.bind('load.drupal-overlay', { self: this.$iframeB[0], sibling: this.$iframeA }, $.proxy(this, 'loadChild')); |
||
119 | |||
120 | // Add a second class "drupal-overlay-open" to indicate these event handlers
|
||
121 | // should only be bound when the overlay is open.
|
||
122 | var eventClass = '.drupal-overlay.drupal-overlay-open'; |
||
123 | $(window)
|
||
124 | .bind('resize' + eventClass, $.proxy(this, 'eventhandlerOuterResize')); |
||
125 | $(document)
|
||
126 | .bind('drupalOverlayLoad' + eventClass, $.proxy(this, 'eventhandlerOuterResize')) |
||
127 | .bind('drupalOverlayReady' + eventClass +
|
||
128 | ' drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerSyncURLFragment')) |
||
129 | .bind('drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerRefreshPage')) |
||
130 | .bind('drupalOverlayBeforeClose' + eventClass +
|
||
131 | ' drupalOverlayBeforeLoad' + eventClass +
|
||
132 | ' drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerDispatchEvent')); |
||
133 | |||
134 | if ($('.overlay-displace-top, .overlay-displace-bottom').length) { |
||
135 | $(document)
|
||
136 | .bind('drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerAlterDisplacedElements')) |
||
137 | .bind('drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerRestoreDisplacedElements')); |
||
138 | } |
||
139 | }; |
||
140 | |||
141 | /**
|
||
142 | * Load the given URL into the overlay iframe.
|
||
143 | *
|
||
144 | * Use this method to change the URL being loaded in the overlay if it is
|
||
145 | * already open.
|
||
146 | *
|
||
147 | * @return
|
||
148 | * TRUE if URL is loaded into the overlay, FALSE otherwise.
|
||
149 | */
|
||
150 | Drupal.overlay.load = function (url) { |
||
151 | if (!this.isOpen) { |
||
152 | return false; |
||
153 | } |
||
154 | |||
155 | // Allow other scripts to respond to this event.
|
||
156 | $(document).trigger('drupalOverlayBeforeLoad'); |
||
157 | |||
158 | $(document.documentElement).addClass('overlay-loading'); |
||
159 | |||
160 | // The contentDocument property is not supported in IE until IE8.
|
||
161 | var iframeDocument = this.inactiveFrame[0].contentDocument || this.inactiveFrame[0].contentWindow.document; |
||
162 | |||
163 | // location.replace doesn't create a history entry. location.href does.
|
||
164 | // In this case, we want location.replace, as we're creating the history
|
||
165 | // entry using URL fragments.
|
||
166 | iframeDocument.location.replace(url); |
||
167 | |||
168 | return true; |
||
169 | }; |
||
170 | |||
171 | /**
|
||
172 | * Close the overlay and remove markup related to it from the document.
|
||
173 | *
|
||
174 | * @return
|
||
175 | * TRUE if the overlay was closed, FALSE otherwise.
|
||
176 | */
|
||
177 | Drupal.overlay.close = function () { |
||
178 | // Prevent double execution when close is requested more than once.
|
||
179 | if (!this.isOpen || this.isClosing) { |
||
180 | return false; |
||
181 | } |
||
182 | |||
183 | // Allow other scripts to respond to this event.
|
||
184 | var event = $.Event('drupalOverlayBeforeClose'); |
||
185 | $(document).trigger(event);
|
||
186 | // If a handler returned false, the close will be prevented.
|
||
187 | if (event.isDefaultPrevented()) {
|
||
188 | return false; |
||
189 | } |
||
190 | |||
191 | this.isClosing = true; |
||
192 | this.isOpen = false; |
||
193 | $(document.documentElement).removeClass('overlay-open'); |
||
194 | // Restore the original document title.
|
||
195 | document.title = this.originalTitle;
|
||
196 | this.makeDocumentTabbable();
|
||
197 | |||
198 | // Allow other scripts to respond to this event.
|
||
199 | $(document).trigger('drupalOverlayClose'); |
||
200 | |||
201 | // When the iframe is still loading don't destroy it immediately but after
|
||
202 | // the content is loaded (see Drupal.overlay.loadChild).
|
||
203 | if (!this.isLoading) { |
||
204 | this.destroy();
|
||
205 | this.isClosing = false; |
||
206 | } |
||
207 | return true; |
||
208 | }; |
||
209 | |||
210 | /**
|
||
211 | * Destroy the overlay.
|
||
212 | */
|
||
213 | Drupal.overlay.destroy = function () { |
||
214 | $([document, window]).unbind('.drupal-overlay-open'); |
||
215 | this.$container.remove(); |
||
216 | |||
217 | this.$container = null; |
||
218 | this.$iframeA = null; |
||
219 | this.$iframeB = null; |
||
220 | |||
221 | this.iframeWindow = null; |
||
222 | }; |
||
223 | |||
224 | /**
|
||
225 | * Redirect the overlay parent window to the given URL.
|
||
226 | *
|
||
227 | * @param url
|
||
228 | * Can be an absolute URL or a relative link to the domain root.
|
||
229 | */
|
||
230 | Drupal.overlay.redirect = function (url) { |
||
231 | // Create a native Link object, so we can use its object methods.
|
||
232 | var link = $(url.link(url)).get(0); |
||
233 | |||
234 | // If the link is already open, force the hashchange event to simulate reload.
|
||
235 | if (window.location.href == link.href) {
|
||
236 | $(window).triggerHandler('hashchange.drupal-overlay'); |
||
237 | } |
||
238 | |||
239 | window.location.href = link.href; |
||
240 | return true; |
||
241 | }; |
||
242 | |||
243 | /**
|
||
244 | * Bind the child window.
|
||
245 | *
|
||
246 | * Note that this function is fired earlier than Drupal.overlay.loadChild.
|
||
247 | */
|
||
248 | Drupal.overlay.bindChild = function (iframeWindow, isClosing) { |
||
249 | this.iframeWindow = iframeWindow;
|
||
250 | |||
251 | // We are done if the child window is closing.
|
||
252 | if (isClosing || this.isClosing || !this.isOpen) { |
||
253 | return;
|
||
254 | } |
||
255 | |||
256 | // Allow other scripts to respond to this event.
|
||
257 | $(document).trigger('drupalOverlayReady'); |
||
258 | }; |
||
259 | |||
260 | /**
|
||
261 | * Event handler: load event handler for the overlay iframe.
|
||
262 | *
|
||
263 | * @param event
|
||
264 | * Event being triggered, with the following restrictions:
|
||
265 | * - event.type: load
|
||
266 | * - event.currentTarget: iframe
|
||
267 | */
|
||
268 | Drupal.overlay.loadChild = function (event) { |
||
269 | var iframe = event.data.self;
|
||
270 | var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
|
||
271 | var iframeWindow = iframeDocument.defaultView || iframeDocument.parentWindow;
|
||
272 | if (iframeWindow.location == 'about:blank') { |
||
273 | return;
|
||
274 | } |
||
275 | |||
276 | this.isLoading = false; |
||
277 | $(document.documentElement).removeClass('overlay-loading'); |
||
278 | event.data.sibling.removeClass('overlay-active').attr({ 'tabindex': -1 }); |
||
279 | |||
280 | // Only continue when overlay is still open and not closing.
|
||
281 | if (this.isOpen && !this.isClosing) { |
||
282 | // And child document is an actual overlayChild.
|
||
283 | if (iframeWindow.Drupal && iframeWindow.Drupal.overlayChild) {
|
||
284 | // Replace the document title with title of iframe.
|
||
285 | document.title = iframeWindow.document.title; |
||
286 | |||
287 | this.activeFrame = $(iframe) |
||
288 | .addClass('overlay-active')
|
||
289 | // Add a title attribute to the iframe for accessibility.
|
||
290 | .attr('title', Drupal.t('@title dialog', { '@title': iframeWindow.jQuery('#overlay-title').text() })).removeAttr('tabindex'); |
||
291 | this.inactiveFrame = event.data.sibling;
|
||
292 | |||
293 | // Load an empty document into the inactive iframe.
|
||
294 | (this.inactiveFrame[0].contentDocument || this.inactiveFrame[0].contentWindow.document).location.replace('about:blank'); |
||
295 | |||
296 | // Move the focus to just before the "skip to main content" link inside
|
||
297 | // the overlay.
|
||
298 | this.activeFrame.focus();
|
||
299 | var skipLink = iframeWindow.jQuery('a:first'); |
||
300 | Drupal.overlay.setFocusBefore(skipLink, iframeWindow.document); |
||
301 | |||
302 | // Allow other scripts to respond to this event.
|
||
303 | $(document).trigger('drupalOverlayLoad'); |
||
304 | } |
||
305 | else {
|
||
306 | window.location = iframeWindow.location.href.replace(/([?&]?)render=overlay&?/g, '$1').replace(/\?$/, ''); |
||
307 | } |
||
308 | } |
||
309 | else {
|
||
310 | this.destroy();
|
||
311 | } |
||
312 | }; |
||
313 | |||
314 | /**
|
||
315 | * Creates a placeholder element to receive document focus.
|
||
316 | *
|
||
317 | * Setting the document focus to a link will make it visible, even if it's a
|
||
318 | * "skip to main content" link that should normally be visible only when the
|
||
319 | * user tabs to it. This function can be used to set the document focus to
|
||
320 | * just before such an invisible link.
|
||
321 | *
|
||
322 | * @param $element
|
||
323 | * The jQuery element that should receive focus on the next tab press.
|
||
324 | * @param document
|
||
325 | * The iframe window element to which the placeholder should be added. The
|
||
326 | * placeholder element has to be created inside the same iframe as the element
|
||
327 | * it precedes, to keep IE happy. (http://bugs.jquery.com/ticket/4059)
|
||
328 | */
|
||
329 | Drupal.overlay.setFocusBefore = function ($element, document) { |
||
330 | // Create an anchor inside the placeholder document.
|
||
331 | var placeholder = document.createElement('a'); |
||
332 | var $placeholder = $(placeholder).addClass('element-invisible').attr('href', '#'); |
||
333 | // Put the placeholder where it belongs, and set the document focus to it.
|
||
334 | $placeholder.insertBefore($element); |
||
335 | $placeholder.focus();
|
||
336 | // Make the placeholder disappear as soon as it loses focus, so that it
|
||
337 | // doesn't appear in the tab order again.
|
||
338 | $placeholder.one('blur', function () { |
||
339 | $(this).remove(); |
||
340 | }); |
||
341 | }; |
||
342 | |||
343 | /**
|
||
344 | * Check if the given link is in the administrative section of the site.
|
||
345 | *
|
||
346 | * @param url
|
||
347 | * The URL to be tested.
|
||
348 | *
|
||
349 | * @return boolean
|
||
350 | * TRUE if the URL represents an administrative link, FALSE otherwise.
|
||
351 | */
|
||
352 | Drupal.overlay.isAdminLink = function (url) { |
||
353 | 00be1f1f | Julien Enselme | if (!Drupal.urlIsLocal(url)) {
|
354 | 85ad3d82 | Assos Assos | return false; |
355 | } |
||
356 | |||
357 | var path = this.getPath(url); |
||
358 | |||
359 | // Turn the list of administrative paths into a regular expression.
|
||
360 | if (!this.adminPathRegExp) { |
||
361 | var prefix = ''; |
||
362 | if (Drupal.settings.overlay.pathPrefixes.length) {
|
||
363 | // Allow path prefixes used for language negatiation followed by slash,
|
||
364 | // and the empty string.
|
||
365 | prefix = '(' + Drupal.settings.overlay.pathPrefixes.join('/|') + '/|)'; |
||
366 | } |
||
367 | var adminPaths = '^' + prefix + '(' + Drupal.settings.overlay.paths.admin.replace(/\s+/g, '|') + ')$'; |
||
368 | var nonAdminPaths = '^' + prefix + '(' + Drupal.settings.overlay.paths.non_admin.replace(/\s+/g, '|') + ')$'; |
||
369 | adminPaths = adminPaths.replace(/\*/g, '.*'); |
||
370 | nonAdminPaths = nonAdminPaths.replace(/\*/g, '.*'); |
||
371 | this.adminPathRegExp = new RegExp(adminPaths); |
||
372 | this.nonAdminPathRegExp = new RegExp(nonAdminPaths); |
||
373 | } |
||
374 | |||
375 | return this.adminPathRegExp.exec(path) && !this.nonAdminPathRegExp.exec(path); |
||
376 | }; |
||
377 | |||
378 | /**
|
||
379 | * Determine whether a link is external to the site.
|
||
380 | *
|
||
381 | 00be1f1f | Julien Enselme | * Deprecated. Use Drupal.urlIsLocal() instead.
|
382 | *
|
||
383 | 85ad3d82 | Assos Assos | * @param url
|
384 | * The URL to be tested.
|
||
385 | *
|
||
386 | * @return boolean
|
||
387 | * TRUE if the URL is external to the site, FALSE otherwise.
|
||
388 | */
|
||
389 | Drupal.overlay.isExternalLink = function (url) { |
||
390 | 00be1f1f | Julien Enselme | return !Drupal.urlIsLocal(url);
|
391 | 85ad3d82 | Assos Assos | }; |
392 | |||
393 | 1afa1695 | Assos Assos | /**
|
394 | * Constructs an internal URL (relative to this site) from the provided path.
|
||
395 | *
|
||
396 | * For example, if the provided path is 'admin' and the site is installed at
|
||
397 | * http://example.com/drupal, this function will return '/drupal/admin'.
|
||
398 | *
|
||
399 | * @param path
|
||
400 | * The internal path, without any leading slash.
|
||
401 | *
|
||
402 | * @return
|
||
403 | * The internal URL derived from the provided path, or null if a valid
|
||
404 | * internal path cannot be constructed (for example, if an attempt to create
|
||
405 | * an external link is detected).
|
||
406 | */
|
||
407 | Drupal.overlay.getInternalUrl = function (path) { |
||
408 | var url = Drupal.settings.basePath + path;
|
||
409 | 00be1f1f | Julien Enselme | if (Drupal.urlIsLocal(url)) {
|
410 | 1afa1695 | Assos Assos | return url;
|
411 | } |
||
412 | }; |
||
413 | |||
414 | 85ad3d82 | Assos Assos | /**
|
415 | * Event handler: resizes overlay according to the size of the parent window.
|
||
416 | *
|
||
417 | * @param event
|
||
418 | * Event being triggered, with the following restrictions:
|
||
419 | * - event.type: any
|
||
420 | * - event.currentTarget: any
|
||
421 | */
|
||
422 | Drupal.overlay.eventhandlerOuterResize = function (event) { |
||
423 | // Proceed only if the overlay still exists.
|
||
424 | if (!(this.isOpen || this.isOpening) || this.isClosing || !this.iframeWindow) { |
||
425 | return;
|
||
426 | } |
||
427 | |||
428 | // IE6 uses position:absolute instead of position:fixed.
|
||
429 | if (typeof document.body.style.maxHeight != 'string') { |
||
430 | this.activeFrame.height($(window).height()); |
||
431 | } |
||
432 | |||
433 | // Allow other scripts to respond to this event.
|
||
434 | $(document).trigger('drupalOverlayResize'); |
||
435 | }; |
||
436 | |||
437 | /**
|
||
438 | * Event handler: resizes displaced elements so they won't overlap the scrollbar
|
||
439 | * of overlay's iframe.
|
||
440 | *
|
||
441 | * @param event
|
||
442 | * Event being triggered, with the following restrictions:
|
||
443 | * - event.type: any
|
||
444 | * - event.currentTarget: any
|
||
445 | */
|
||
446 | Drupal.overlay.eventhandlerAlterDisplacedElements = function (event) { |
||
447 | // Proceed only if the overlay still exists.
|
||
448 | if (!(this.isOpen || this.isOpening) || this.isClosing || !this.iframeWindow) { |
||
449 | return;
|
||
450 | } |
||
451 | |||
452 | $(this.iframeWindow.document.body).css({ |
||
453 | marginTop: Drupal.overlay.getDisplacement('top'), |
||
454 | marginBottom: Drupal.overlay.getDisplacement('bottom') |
||
455 | }) |
||
456 | // IE7 isn't reflowing the document immediately.
|
||
457 | // @todo This might be fixed in a cleaner way.
|
||
458 | .addClass('overlay-trigger-reflow').removeClass('overlay-trigger-reflow'); |
||
459 | |||
460 | var documentHeight = this.iframeWindow.document.body.clientHeight; |
||
461 | var documentWidth = this.iframeWindow.document.body.clientWidth; |
||
462 | // IE6 doesn't support maxWidth, use width instead.
|
||
463 | var maxWidthName = (typeof document.body.style.maxWidth == 'string') ? 'maxWidth' : 'width'; |
||
464 | |||
465 | if (Drupal.overlay.leftSidedScrollbarOffset === undefined && $(document.documentElement).attr('dir') === 'rtl') { |
||
466 | // We can't use element.clientLeft to detect whether scrollbars are placed
|
||
467 | // on the left side of the element when direction is set to "rtl" as most
|
||
468 | // browsers dont't support it correctly.
|
||
469 | // http://www.gtalbot.org/BugzillaSection/DocumentAllDHTMLproperties.html
|
||
470 | // There seems to be absolutely no way to detect whether the scrollbar
|
||
471 | // is on the left side in Opera; always expect scrollbar to be on the left.
|
||
472 | if ($.browser.opera) { |
||
473 | Drupal.overlay.leftSidedScrollbarOffset = document.documentElement.clientWidth - this.iframeWindow.document.documentElement.clientWidth + this.iframeWindow.document.documentElement.clientLeft; |
||
474 | } |
||
475 | else if (this.iframeWindow.document.documentElement.clientLeft) { |
||
476 | Drupal.overlay.leftSidedScrollbarOffset = this.iframeWindow.document.documentElement.clientLeft;
|
||
477 | } |
||
478 | else {
|
||
479 | var el1 = $('<div style="direction: rtl; overflow: scroll;"></div>').appendTo(document.body); |
||
480 | var el2 = $('<div></div>').appendTo(el1); |
||
481 | Drupal.overlay.leftSidedScrollbarOffset = parseInt(el2[0].offsetLeft - el1[0].offsetLeft); |
||
482 | el1.remove(); |
||
483 | } |
||
484 | } |
||
485 | |||
486 | // Consider any element that should be visible above the overlay (such as
|
||
487 | // a toolbar).
|
||
488 | $('.overlay-displace-top, .overlay-displace-bottom').each(function () { |
||
489 | var data = $(this).data(); |
||
490 | var maxWidth = documentWidth;
|
||
491 | // In IE, Shadow filter makes element to overlap the scrollbar with 1px.
|
||
492 | if (this.filters && this.filters.length && this.filters.item('DXImageTransform.Microsoft.Shadow')) { |
||
493 | maxWidth -= 1;
|
||
494 | } |
||
495 | |||
496 | if (Drupal.overlay.leftSidedScrollbarOffset) {
|
||
497 | $(this).css('left', Drupal.overlay.leftSidedScrollbarOffset); |
||
498 | } |
||
499 | |||
500 | // Prevent displaced elements overlapping window's scrollbar.
|
||
501 | var currentMaxWidth = parseInt($(this).css(maxWidthName)); |
||
502 | if ((data.drupalOverlay && data.drupalOverlay.maxWidth) || isNaN(currentMaxWidth) || currentMaxWidth > maxWidth || currentMaxWidth <= 0) { |
||
503 | $(this).css(maxWidthName, maxWidth); |
||
504 | (data.drupalOverlay = data.drupalOverlay || {}).maxWidth = true;
|
||
505 | } |
||
506 | |||
507 | // Use a more rigorous approach if the displaced element still overlaps
|
||
508 | // window's scrollbar; clip the element on the right.
|
||
509 | var offset = $(this).offset(); |
||
510 | var offsetRight = offset.left + $(this).outerWidth(); |
||
511 | if ((data.drupalOverlay && data.drupalOverlay.clip) || offsetRight > maxWidth) {
|
||
512 | if (Drupal.overlay.leftSidedScrollbarOffset) {
|
||
513 | $(this).css('clip', 'rect(auto, auto, ' + (documentHeight - offset.top) + 'px, ' + (Drupal.overlay.leftSidedScrollbarOffset + 2) + 'px)'); |
||
514 | } |
||
515 | else {
|
||
516 | $(this).css('clip', 'rect(auto, ' + (maxWidth - offset.left) + 'px, ' + (documentHeight - offset.top) + 'px, auto)'); |
||
517 | } |
||
518 | (data.drupalOverlay = data.drupalOverlay || {}).clip = true;
|
||
519 | } |
||
520 | }); |
||
521 | }; |
||
522 | |||
523 | /**
|
||
524 | * Event handler: restores size of displaced elements as they were before
|
||
525 | * overlay was opened.
|
||
526 | *
|
||
527 | * @param event
|
||
528 | * Event being triggered, with the following restrictions:
|
||
529 | * - event.type: any
|
||
530 | * - event.currentTarget: any
|
||
531 | */
|
||
532 | Drupal.overlay.eventhandlerRestoreDisplacedElements = function (event) { |
||
533 | var $displacedElements = $('.overlay-displace-top, .overlay-displace-bottom'); |
||
534 | try {
|
||
535 | $displacedElements.css({ maxWidth: '', clip: '' }); |
||
536 | } |
||
537 | // IE bug that doesn't allow unsetting style.clip (http://dev.jquery.com/ticket/6512).
|
||
538 | catch (err) {
|
||
539 | $displacedElements.attr('style', function (index, attr) { |
||
540 | return attr.replace(/clip\s*:\s*rect\([^)]+\);?/i, ''); |
||
541 | }); |
||
542 | } |
||
543 | }; |
||
544 | |||
545 | /**
|
||
546 | * Event handler: overrides href of administrative links to be opened in
|
||
547 | * the overlay.
|
||
548 | *
|
||
549 | * This click event handler should be bound to any document (for example the
|
||
550 | * overlay iframe) of which you want links to open in the overlay.
|
||
551 | *
|
||
552 | * @param event
|
||
553 | * Event being triggered, with the following restrictions:
|
||
554 | * - event.type: click, mouseup
|
||
555 | * - event.currentTarget: document
|
||
556 | *
|
||
557 | * @see Drupal.overlayChild.behaviors.addClickHandler
|
||
558 | */
|
||
559 | Drupal.overlay.eventhandlerOverrideLink = function (event) { |
||
560 | // In some browsers the click event isn't fired for right-clicks. Use the
|
||
561 | // mouseup event for right-clicks and the click event for everything else.
|
||
562 | if ((event.type == 'click' && event.button == 2) || (event.type == 'mouseup' && event.button != 2)) { |
||
563 | return;
|
||
564 | } |
||
565 | |||
566 | var $target = $(event.target); |
||
567 | |||
568 | // Only continue if clicked target (or one of its parents) is a link.
|
||
569 | if (!$target.is('a')) { |
||
570 | $target = $target.closest('a'); |
||
571 | if (!$target.length) { |
||
572 | return;
|
||
573 | } |
||
574 | } |
||
575 | |||
576 | // Never open links in the overlay that contain the overlay-exclude class.
|
||
577 | if ($target.hasClass('overlay-exclude')) { |
||
578 | return;
|
||
579 | } |
||
580 | |||
581 | // Close the overlay when the link contains the overlay-close class.
|
||
582 | if ($target.hasClass('overlay-close')) { |
||
583 | // Clearing the overlay URL fragment will close the overlay.
|
||
584 | $.bbq.removeState('overlay'); |
||
585 | return;
|
||
586 | } |
||
587 | |||
588 | var target = $target[0]; |
||
589 | var href = target.href;
|
||
590 | // Only handle links that have an href attribute and use the HTTP(S) protocol.
|
||
591 | if (href != undefined && href != '' && target.protocol.match(/^https?\:/)) { |
||
592 | var anchor = href.replace(target.ownerDocument.location.href, ''); |
||
593 | // Skip anchor links.
|
||
594 | if (anchor.length == 0 || anchor.charAt(0) == '#') { |
||
595 | return;
|
||
596 | } |
||
597 | // Open admin links in the overlay.
|
||
598 | else if (this.isAdminLink(href)) { |
||
599 | // If the link contains the overlay-restore class and the overlay-context
|
||
600 | // state is set, also update the parent window's location.
|
||
601 | var parentLocation = ($target.hasClass('overlay-restore') && typeof $.bbq.getState('overlay-context') == 'string') |
||
602 | 1afa1695 | Assos Assos | ? this.getInternalUrl($.bbq.getState('overlay-context')) |
603 | 85ad3d82 | Assos Assos | : null;
|
604 | href = this.fragmentizeLink($target.get(0), parentLocation); |
||
605 | // Only override default behavior when left-clicking and user is not
|
||
606 | // pressing the ALT, CTRL, META (Command key on the Macintosh keyboard)
|
||
607 | // or SHIFT key.
|
||
608 | if (event.button == 0 && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { |
||
609 | // Redirect to a fragmentized href. This will trigger a hashchange event.
|
||
610 | this.redirect(href);
|
||
611 | // Prevent default action and further propagation of the event.
|
||
612 | return false; |
||
613 | } |
||
614 | // Otherwise alter clicked link's href. This is being picked up by
|
||
615 | // the default action handler.
|
||
616 | else {
|
||
617 | $target
|
||
618 | // Restore link's href attribute on blur or next click.
|
||
619 | .one('blur mousedown', { target: target, href: target.href }, function (event) { $(event.data.target).attr('href', event.data.href); }) |
||
620 | .attr('href', href);
|
||
621 | } |
||
622 | } |
||
623 | // Non-admin links should close the overlay and open in the main window,
|
||
624 | // which is the default action for a link. We only need to handle them
|
||
625 | // if the overlay is open and the clicked link is inside the overlay iframe.
|
||
626 | else if (this.isOpen && target.ownerDocument === this.iframeWindow.document) { |
||
627 | // Open external links in the immediate parent of the frame, unless the
|
||
628 | // link already has a different target.
|
||
629 | if (target.hostname != window.location.hostname) {
|
||
630 | if (!$target.attr('target')) { |
||
631 | $target.attr('target', '_parent'); |
||
632 | } |
||
633 | } |
||
634 | else {
|
||
635 | // Add the overlay-context state to the link, so "overlay-restore" links
|
||
636 | // can restore the context.
|
||
637 | if ($target[0].hash) { |
||
638 | // Leave links with an existing fragment alone. Adding an extra
|
||
639 | // parameter to a link like "node/1#section-1" breaks the link.
|
||
640 | } |
||
641 | else {
|
||
642 | // For links with no existing fragment, add the overlay context.
|
||
643 | $target.attr('href', $.param.fragment(href, { 'overlay-context': this.getPath(window.location) + window.location.search })); |
||
644 | } |
||
645 | |||
646 | // When the link has a destination query parameter and that destination
|
||
647 | // is an admin link we need to fragmentize it. This will make it reopen
|
||
648 | // in the overlay.
|
||
649 | var params = $.deparam.querystring(href); |
||
650 | if (params.destination && this.isAdminLink(params.destination)) { |
||
651 | var fragmentizedDestination = $.param.fragment(this.getPath(window.location), { overlay: params.destination }); |
||
652 | $target.attr('href', $.param.querystring(href, { destination: fragmentizedDestination })); |
||
653 | } |
||
654 | |||
655 | // Make the link open in the immediate parent of the frame, unless the
|
||
656 | // link already has a different target.
|
||
657 | if (!$target.attr('target')) { |
||
658 | $target.attr('target', '_parent'); |
||
659 | } |
||
660 | } |
||
661 | } |
||
662 | } |
||
663 | }; |
||
664 | |||
665 | /**
|
||
666 | * Event handler: opens or closes the overlay based on the current URL fragment.
|
||
667 | *
|
||
668 | * @param event
|
||
669 | * Event being triggered, with the following restrictions:
|
||
670 | * - event.type: hashchange
|
||
671 | * - event.currentTarget: document
|
||
672 | */
|
||
673 | Drupal.overlay.eventhandlerOperateByURLFragment = function (event) { |
||
674 | // If we changed the hash to reflect an internal redirect in the overlay,
|
||
675 | // its location has already been changed, so don't do anything.
|
||
676 | if ($.data(window.location, window.location.href) === 'redirect') { |
||
677 | $.data(window.location, window.location.href, null); |
||
678 | return;
|
||
679 | } |
||
680 | |||
681 | // Get the overlay URL from the current URL fragment.
|
||
682 | 1afa1695 | Assos Assos | var internalUrl = null; |
683 | 85ad3d82 | Assos Assos | var state = $.bbq.getState('overlay'); |
684 | if (state) {
|
||
685 | 1afa1695 | Assos Assos | internalUrl = this.getInternalUrl(state);
|
686 | } |
||
687 | if (internalUrl) {
|
||
688 | 85ad3d82 | Assos Assos | // Append render variable, so the server side can choose the right
|
689 | // rendering and add child frame code to the page if needed.
|
||
690 | 1afa1695 | Assos Assos | var url = $.param.querystring(internalUrl, { render: 'overlay' }); |
691 | 85ad3d82 | Assos Assos | |
692 | this.open(url);
|
||
693 | this.resetActiveClass(this.getPath(Drupal.settings.basePath + state)); |
||
694 | } |
||
695 | // If there is no overlay URL in the fragment and the overlay is (still)
|
||
696 | // open, close the overlay.
|
||
697 | else if (this.isOpen && !this.isClosing) { |
||
698 | this.close();
|
||
699 | this.resetActiveClass(this.getPath(window.location)); |
||
700 | } |
||
701 | }; |
||
702 | |||
703 | /**
|
||
704 | * Event handler: makes sure the internal overlay URL is reflected in the parent
|
||
705 | * URL fragment.
|
||
706 | *
|
||
707 | * Normally the parent URL fragment determines the overlay location. However, if
|
||
708 | * the overlay redirects internally, the parent doesn't get informed, and the
|
||
709 | * parent URL fragment will be out of date. This is a sanity check to make
|
||
710 | * sure we're in the right place.
|
||
711 | *
|
||
712 | * The parent URL fragment is also not updated automatically when overlay's
|
||
713 | * open, close or load functions are used directly (instead of through
|
||
714 | * eventhandlerOperateByURLFragment).
|
||
715 | *
|
||
716 | * @param event
|
||
717 | * Event being triggered, with the following restrictions:
|
||
718 | * - event.type: drupalOverlayReady, drupalOverlayClose
|
||
719 | * - event.currentTarget: document
|
||
720 | */
|
||
721 | Drupal.overlay.eventhandlerSyncURLFragment = function (event) { |
||
722 | if (this.isOpen) { |
||
723 | var expected = $.bbq.getState('overlay'); |
||
724 | // This is just a sanity check, so we're comparing paths, not query strings.
|
||
725 | if (this.getPath(Drupal.settings.basePath + expected) != this.getPath(this.iframeWindow.document.location)) { |
||
726 | // There may have been a redirect inside the child overlay window that the
|
||
727 | // parent wasn't aware of. Update the parent URL fragment appropriately.
|
||
728 | var newLocation = Drupal.overlay.fragmentizeLink(this.iframeWindow.document.location); |
||
729 | // Set a 'redirect' flag on the new location so the hashchange event handler
|
||
730 | // knows not to change the overlay's content.
|
||
731 | $.data(window.location, newLocation, 'redirect'); |
||
732 | // Use location.replace() so we don't create an extra history entry.
|
||
733 | window.location.replace(newLocation); |
||
734 | } |
||
735 | } |
||
736 | else {
|
||
737 | $.bbq.removeState('overlay'); |
||
738 | } |
||
739 | }; |
||
740 | |||
741 | /**
|
||
742 | * Event handler: if the child window suggested that the parent refresh on
|
||
743 | * close, force a page refresh.
|
||
744 | *
|
||
745 | * @param event
|
||
746 | * Event being triggered, with the following restrictions:
|
||
747 | * - event.type: drupalOverlayClose
|
||
748 | * - event.currentTarget: document
|
||
749 | */
|
||
750 | Drupal.overlay.eventhandlerRefreshPage = function (event) { |
||
751 | if (Drupal.overlay.refreshPage) {
|
||
752 | window.location.reload(true);
|
||
753 | } |
||
754 | }; |
||
755 | |||
756 | /**
|
||
757 | * Event handler: dispatches events to the overlay document.
|
||
758 | *
|
||
759 | * @param event
|
||
760 | * Event being triggered, with the following restrictions:
|
||
761 | * - event.type: any
|
||
762 | * - event.currentTarget: any
|
||
763 | */
|
||
764 | Drupal.overlay.eventhandlerDispatchEvent = function (event) { |
||
765 | if (this.iframeWindow && this.iframeWindow.document) { |
||
766 | this.iframeWindow.jQuery(this.iframeWindow.document).trigger(event); |
||
767 | } |
||
768 | }; |
||
769 | |||
770 | /**
|
||
771 | * Make a regular admin link into a URL that will trigger the overlay to open.
|
||
772 | *
|
||
773 | * @param link
|
||
774 | * A JavaScript Link object (i.e. an <a> element).
|
||
775 | * @param parentLocation
|
||
776 | * (optional) URL to override the parent window's location with.
|
||
777 | *
|
||
778 | * @return
|
||
779 | * A URL that will trigger the overlay (in the form
|
||
780 | * /node/1#overlay=admin/config).
|
||
781 | */
|
||
782 | Drupal.overlay.fragmentizeLink = function (link, parentLocation) { |
||
783 | // Don't operate on links that are already overlay-ready.
|
||
784 | var params = $.deparam.fragment(link.href); |
||
785 | if (params.overlay) {
|
||
786 | return link.href;
|
||
787 | } |
||
788 | |||
789 | // Determine the link's original destination. Set ignorePathFromQueryString to
|
||
790 | // true to prevent transforming this link into a clean URL while clean URLs
|
||
791 | // may be disabled.
|
||
792 | var path = this.getPath(link, true); |
||
793 | // Preserve existing query and fragment parameters in the URL, except for
|
||
794 | // "render=overlay" which is re-added in Drupal.overlay.eventhandlerOperateByURLFragment.
|
||
795 | var destination = path + link.search.replace(/&?render=overlay/, '').replace(/\?$/, '') + link.hash; |
||
796 | |||
797 | // Assemble and return the overlay-ready link.
|
||
798 | return $.param.fragment(parentLocation || window.location.href, { overlay: destination }); |
||
799 | }; |
||
800 | |||
801 | /**
|
||
802 | * Refresh any regions of the page that are displayed outside the overlay.
|
||
803 | *
|
||
804 | * @param data
|
||
805 | * An array of objects with information on the page regions to be refreshed.
|
||
806 | * For each object, the key is a CSS class identifying the region to be
|
||
807 | * refreshed, and the value represents the section of the Drupal $page array
|
||
808 | * corresponding to this region.
|
||
809 | */
|
||
810 | Drupal.overlay.refreshRegions = function (data) { |
||
811 | $.each(data, function () { |
||
812 | var region_info = this; |
||
813 | $.each(region_info, function (regionClass) { |
||
814 | var regionName = region_info[regionClass];
|
||
815 | var regionSelector = '.' + regionClass; |
||
816 | // Allow special behaviors to detach.
|
||
817 | Drupal.detachBehaviors($(regionSelector));
|
||
818 | $.get(Drupal.settings.basePath + Drupal.settings.overlay.ajaxCallback + '/' + regionName, function (newElement) { |
||
819 | $(regionSelector).replaceWith($(newElement)); |
||
820 | Drupal.attachBehaviors($(regionSelector), Drupal.settings);
|
||
821 | }); |
||
822 | }); |
||
823 | }); |
||
824 | }; |
||
825 | |||
826 | /**
|
||
827 | * Reset the active class on links in displaced elements according to
|
||
828 | * given path.
|
||
829 | *
|
||
830 | * @param activePath
|
||
831 | * Path to match links against.
|
||
832 | */
|
||
833 | Drupal.overlay.resetActiveClass = function(activePath) { |
||
834 | var self = this; |
||
835 | var windowDomain = window.location.protocol + window.location.hostname;
|
||
836 | |||
837 | $('.overlay-displace-top, .overlay-displace-bottom') |
||
838 | .find('a[href]')
|
||
839 | // Remove active class from all links in displaced elements.
|
||
840 | .removeClass('active')
|
||
841 | // Add active class to links that match activePath.
|
||
842 | .each(function () {
|
||
843 | var linkDomain = this.protocol + this.hostname; |
||
844 | var linkPath = self.getPath(this); |
||
845 | |||
846 | // A link matches if it is part of the active trail of activePath, except
|
||
847 | // for frontpage links.
|
||
848 | if (linkDomain == windowDomain && (activePath + '/').indexOf(linkPath + '/') === 0 && (linkPath !== '' || activePath === '')) { |
||
849 | $(this).addClass('active'); |
||
850 | } |
||
851 | }); |
||
852 | }; |
||
853 | |||
854 | /**
|
||
855 | * Helper function to get the (corrected) Drupal path of a link.
|
||
856 | *
|
||
857 | * @param link
|
||
858 | * Link object or string to get the Drupal path from.
|
||
859 | * @param ignorePathFromQueryString
|
||
860 | * Boolean whether to ignore path from query string if path appears empty.
|
||
861 | *
|
||
862 | * @return
|
||
863 | * The Drupal path.
|
||
864 | */
|
||
865 | Drupal.overlay.getPath = function (link, ignorePathFromQueryString) { |
||
866 | if (typeof link == 'string') { |
||
867 | // Create a native Link object, so we can use its object methods.
|
||
868 | link = $(link.link(link)).get(0); |
||
869 | } |
||
870 | |||
871 | var path = link.pathname;
|
||
872 | // Ensure a leading slash on the path, omitted in some browsers.
|
||
873 | if (path.charAt(0) != '/') { |
||
874 | path = '/' + path;
|
||
875 | } |
||
876 | path = path.replace(new RegExp(Drupal.settings.basePath + '(?:index.php)?'), ''); |
||
877 | if (path == '' && !ignorePathFromQueryString) { |
||
878 | // If the path appears empty, it might mean the path is represented in the
|
||
879 | // query string (clean URLs are not used).
|
||
880 | var match = new RegExp('([?&])q=(.+)([&#]|$)').exec(link.search); |
||
881 | if (match && match.length == 4) { |
||
882 | path = match[2];
|
||
883 | } |
||
884 | } |
||
885 | |||
886 | return path;
|
||
887 | }; |
||
888 | |||
889 | /**
|
||
890 | * Get the total displacement of given region.
|
||
891 | *
|
||
892 | * @param region
|
||
893 | * Region name. Either "top" or "bottom".
|
||
894 | *
|
||
895 | * @return
|
||
896 | * The total displacement of given region in pixels.
|
||
897 | */
|
||
898 | Drupal.overlay.getDisplacement = function (region) { |
||
899 | var displacement = 0; |
||
900 | var lastDisplaced = $('.overlay-displace-' + region + ':last'); |
||
901 | if (lastDisplaced.length) {
|
||
902 | displacement = lastDisplaced.offset().top + lastDisplaced.outerHeight(); |
||
903 | |||
904 | // In modern browsers (including IE9), when box-shadow is defined, use the
|
||
905 | // normal height.
|
||
906 | var cssBoxShadowValue = lastDisplaced.css('box-shadow'); |
||
907 | var boxShadow = (typeof cssBoxShadowValue !== 'undefined' && cssBoxShadowValue !== 'none'); |
||
908 | // In IE8 and below, we use the shadow filter to apply box-shadow styles to
|
||
909 | // the toolbar. It adds some extra height that we need to remove.
|
||
910 | if (!boxShadow && /DXImageTransform\.Microsoft\.Shadow/.test(lastDisplaced.css('filter'))) { |
||
911 | displacement -= lastDisplaced[0].filters.item('DXImageTransform.Microsoft.Shadow').strength; |
||
912 | displacement = Math.max(0, displacement);
|
||
913 | } |
||
914 | } |
||
915 | return displacement;
|
||
916 | }; |
||
917 | |||
918 | /**
|
||
919 | * Makes elements outside the overlay unreachable via the tab key.
|
||
920 | *
|
||
921 | * @param context
|
||
922 | * The part of the DOM that should have its tabindexes changed. Defaults to
|
||
923 | * the entire page.
|
||
924 | */
|
||
925 | Drupal.overlay.makeDocumentUntabbable = function (context) { |
||
926 | // Manipulating tabindexes for the entire document is unacceptably slow in IE6
|
||
927 | // and IE7, so in those browsers, the underlying page will still be reachable
|
||
928 | // via the tab key. However, we still make the links within the Disable
|
||
929 | // message unreachable, because the same message also exists within the
|
||
930 | // child document. The duplicate copy in the underlying document is only for
|
||
931 | // assisting screen-reader users navigating the document with reading commands
|
||
932 | // that follow markup order rather than tab order.
|
||
933 | if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 8) { |
||
934 | $('#overlay-disable-message a', context).attr('tabindex', -1); |
||
935 | return;
|
||
936 | } |
||
937 | |||
938 | context = context || document.body; |
||
939 | var $overlay, $tabbable, $hasTabindex; |
||
940 | |||
941 | // Determine which elements on the page already have a tabindex.
|
||
942 | $hasTabindex = $('[tabindex] :not(.overlay-element)', context); |
||
943 | // Record the tabindex for each element, so we can restore it later.
|
||
944 | $hasTabindex.each(Drupal.overlay._recordTabindex);
|
||
945 | // Add the tabbable elements from the current context to any that we might
|
||
946 | // have previously recorded.
|
||
947 | Drupal.overlay._hasTabindex = $hasTabindex.add(Drupal.overlay._hasTabindex);
|
||
948 | |||
949 | // Set tabindex to -1 on everything outside the overlay and toolbars, so that
|
||
950 | // the underlying page is unreachable.
|
||
951 | |||
952 | // By default, browsers make a, area, button, input, object, select, textarea,
|
||
953 | // and iframe elements reachable via the tab key.
|
||
954 | $tabbable = $('a, area, button, input, object, select, textarea, iframe'); |
||
955 | // If another element (like a div) has a tabindex, it's also tabbable.
|
||
956 | $tabbable = $tabbable.add($hasTabindex); |
||
957 | // Leave links inside the overlay and toolbars alone.
|
||
958 | $overlay = $('.overlay-element, #overlay-container, .overlay-displace-top, .overlay-displace-bottom').find('*'); |
||
959 | $tabbable = $tabbable.not($overlay); |
||
960 | // We now have a list of everything in the underlying document that could
|
||
961 | // possibly be reachable via the tab key. Make it all unreachable.
|
||
962 | $tabbable.attr('tabindex', -1); |
||
963 | }; |
||
964 | |||
965 | /**
|
||
966 | * Restores the original tabindex value of a group of elements.
|
||
967 | *
|
||
968 | * @param context
|
||
969 | * The part of the DOM that should have its tabindexes restored. Defaults to
|
||
970 | * the entire page.
|
||
971 | */
|
||
972 | Drupal.overlay.makeDocumentTabbable = function (context) { |
||
973 | // Manipulating tabindexes is unacceptably slow in IE6 and IE7. In those
|
||
974 | // browsers, the underlying page was never made unreachable via tab, so
|
||
975 | // there is no work to be done here.
|
||
976 | if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 8) { |
||
977 | return;
|
||
978 | } |
||
979 | |||
980 | var $needsTabindex; |
||
981 | context = context || document.body; |
||
982 | |||
983 | // Make the underlying document tabbable again by removing all existing
|
||
984 | // tabindex attributes.
|
||
985 | var $tabindex = $('[tabindex]', context); |
||
986 | if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 8) { |
||
987 | // removeAttr('tabindex') is broken in IE6-7, but the DOM function
|
||
988 | // removeAttribute works.
|
||
989 | var i;
|
||
990 | var length = $tabindex.length; |
||
991 | for (i = 0; i < length; i++) { |
||
992 | $tabindex[i].removeAttribute('tabIndex'); |
||
993 | } |
||
994 | } |
||
995 | else {
|
||
996 | $tabindex.removeAttr('tabindex'); |
||
997 | } |
||
998 | |||
999 | // Restore the tabindex attributes that existed before the overlay was opened.
|
||
1000 | $needsTabindex = $(Drupal.overlay._hasTabindex, context); |
||
1001 | $needsTabindex.each(Drupal.overlay._restoreTabindex);
|
||
1002 | Drupal.overlay._hasTabindex = Drupal.overlay._hasTabindex.not($needsTabindex);
|
||
1003 | }; |
||
1004 | |||
1005 | /**
|
||
1006 | * Record the tabindex for an element, using $.data.
|
||
1007 | *
|
||
1008 | * Meant to be used as a jQuery.fn.each callback.
|
||
1009 | */
|
||
1010 | Drupal.overlay._recordTabindex = function () { |
||
1011 | var $element = $(this); |
||
1012 | var tabindex = $(this).attr('tabindex'); |
||
1013 | $element.data('drupalOverlayOriginalTabIndex', tabindex); |
||
1014 | }; |
||
1015 | |||
1016 | /**
|
||
1017 | * Restore an element's original tabindex.
|
||
1018 | *
|
||
1019 | * Meant to be used as a jQuery.fn.each callback.
|
||
1020 | */
|
||
1021 | Drupal.overlay._restoreTabindex = function () { |
||
1022 | var $element = $(this); |
||
1023 | var tabindex = $element.data('drupalOverlayOriginalTabIndex'); |
||
1024 | $element.attr('tabindex', tabindex); |
||
1025 | }; |
||
1026 | |||
1027 | /**
|
||
1028 | * Theme function to create the overlay iframe element.
|
||
1029 | */
|
||
1030 | Drupal.theme.prototype.overlayContainer = function () { |
||
1031 | return '<div id="overlay-container"><div class="overlay-modal-background"></div></div>'; |
||
1032 | }; |
||
1033 | |||
1034 | /**
|
||
1035 | * Theme function to create an overlay iframe element.
|
||
1036 | */
|
||
1037 | Drupal.theme.prototype.overlayElement = function (url) { |
||
1038 | return '<iframe class="overlay-element" frameborder="0" scrolling="auto" allowtransparency="true"></iframe>'; |
||
1039 | }; |
||
1040 | |||
1041 | })(jQuery); |