### Eclipse Workspace Patch 1.0 #P drupal 7 Index: modules/overlay/overlay-child.js =================================================================== RCS file: /cvs/drupal/drupal/modules/overlay/overlay-child.js,v retrieving revision 1.8 diff -u -r1.8 overlay-child.js --- modules/overlay/overlay-child.js 24 Apr 2010 07:14:29 -0000 1.8 +++ modules/overlay/overlay-child.js 1 May 2010 15:38:28 -0000 @@ -3,30 +3,24 @@ (function ($) { /** - * Overlay object for child windows. - */ -Drupal.overlayChild = Drupal.overlayChild || { processed: false, behaviors: {} }; - -/** * Attach the child dialog behavior to new content. */ Drupal.behaviors.overlayChild = { attach: function (context, settings) { - var self = Drupal.overlayChild; - var settings = settings.overlayChild || {}; - // Make sure this behavior is not processed more than once. - if (self.processed) { + if (this.processed) { return; } - self.processed = true; + this.processed = true; // If we cannot reach the parent window, then we have nothing else to do // here. - if (!$.isPlainObject(parent.Drupal) || !$.isPlainObject(parent.Drupal.overlay)) { + if (!parent.Drupal || !parent.Drupal.overlay) { return; } + var settings = settings.overlayChild || {}; + // If a form has been submitted successfully, then the server side script // may have decided to tell us the parent window to close the popup dialog. if (settings.closeOverlay) { @@ -55,11 +49,20 @@ parent.Drupal.overlay.bindChild(window); // Attach child related behaviors to the iframe document. - self.attachBehaviors(context, settings); + Drupal.overlayChild.attachBehaviors(context, settings); } }; /** + * Overlay object for child windows. + */ +Drupal.overlayChild = Drupal.overlayChild || { + behaviors: {} +}; + +Drupal.overlayChild.prototype = {}; + +/** * Attach child related behaviors to the iframe document. */ Drupal.overlayChild.attachBehaviors = function (context, settings) { @@ -86,7 +89,7 @@ * to bind their own handlers to links and also to prevent overlay's handling. */ Drupal.overlayChild.behaviors.addClickHandler = function (context, settings) { - $(document).bind('click.overlay-event', parent.Drupal.overlay.clickHandler); + $(document).bind('click.drupal-overlay', parent.Drupal.overlay.clickHandler); }; /** @@ -111,4 +114,61 @@ }); }; +/** + * Replace the overlay title with a message while loading another page. + */ +Drupal.overlayChild.behaviors.loading = function (context, settings) { + var text = Drupal.t('Loading...'); + + parent.jQuery(parent.document).bind('drupalOverlayBeforeLoad.drupal-overlay', function () { + $('#overlay-title').text(text); + }); +}; + +/** + * Switch active tab immediately. + */ +Drupal.overlayChild.behaviors.tabs = function (context, settings) { + var $tabsLinks = $('#overlay-tabs > li > a'); + + $('#overlay-tabs > li > a').bind('click', function () { + var active_tab = Drupal.t('(active tab)'); + $tabsLinks.parent().siblings().removeClass('active').find('element-invisible:contains(' + active_tab + ')').appendTo(this); + $(this).parent().addClass('active'); + }); +}; + +/** + * If the shortcut add/delete button exists, move it to the overlay titlebar. + */ +Drupal.overlayChild.behaviors.shortcutAddLink = function (context, settings) { + // Remove any existing shortcut button markup from the titlebar. + $('#overlay-titlebar').find('.add-or-remove-shortcuts').remove(); + // If the shortcut add/delete button exists, move it to the titlebar. + var $addToShortcuts = $('.add-or-remove-shortcuts'); + if ($addToShortcuts.length) { + $addToShortcuts.insertAfter('#overlay-title'); + } +}; + +/** + * Override the tableHeaderOffset callback for tableheader.js. + */ +Drupal.overlayChild.behaviors.tableHeaderOffset = function (context, settings) { + Drupal.overlayChild.originalTableHeaderOffset = Drupal.settings.tableHeaderOffset; + + Drupal.settings.tableHeaderOffset = 'Drupal.overlayChild.tableHeaderOffset'; +}; + +/** + * Callback function Drupal.settings.tableHeaderOffset. + */ +Drupal.overlayChild.tableHeaderOffset = function () { + var offset = parseInt($(document.body).css('marginTop')); + if (Drupal.overlayChild.originalTableHeaderOffset) { + offset += eval(Drupal.overlayChild.originalTableHeaderOffset + '()'); + } + return offset; +}; + })(jQuery); Index: modules/overlay/overlay-parent.css =================================================================== RCS file: /cvs/drupal/drupal/modules/overlay/overlay-parent.css,v retrieving revision 1.14 diff -u -r1.14 overlay-parent.css --- modules/overlay/overlay-parent.css 28 Apr 2010 20:08:39 -0000 1.14 +++ modules/overlay/overlay-parent.css 1 May 2010 15:38:28 -0000 @@ -1,165 +1,44 @@ /* $Id: overlay-parent.css,v 1.14 2010/04/28 20:08:39 dries Exp $ */ -/** - * ui-dialog overlay. - */ -.ui-widget-overlay { - opacity: 1; - filter: none; - /* Using a transparent png renders faster than using opacity */ - background: transparent url(images/background.png) repeat; +html.overlay-open, +html.overlay-open body { + height: 100%; + overflow: hidden; } -body.overlay-autofit { - overflow-y: scroll; +html.overlay-scrollbar { + overflow: scroll; } -/** - * Overlay wrapper. - */ -#overlay-wrapper { +#overlay-container, +.overlay-modal-background, +.overlay-element { position: absolute; top: 0; left: 0; - width: 100%; - z-index: 501; - padding: 20px 0 15px 0; -} - -/** - * jQuery UI Dialog classes. - */ -.overlay { - position: static; - padding-right: 26px; - margin: 0 auto; - width: 88%; - min-width: 700px; - min-height: 100px; -} - -.overlay.ui-widget-content, -.overlay .ui-widget-header { - background: none; - border: none; -} - -.overlay .ui-dialog-titlebar { - white-space: nowrap; - padding: 0 20px; -} - -.overlay .ui-dialog-title { - margin: 0; - padding: 0.3em 0; - color: #fff; - font-size: 20px; -} -.overlay .ui-dialog-title:active, -.overlay .ui-dialog-title:focus { - outline: 0; -} -.overlay .ui-dialog-titlebar-close, -.overlay .ui-dialog-titlebar-close:hover { - display: block; - right: -25px; - top: 100%; - margin: 0; - border: none; - padding: 0; - width: 26px; - height: 36px; - background: transparent url(images/close.png) no-repeat; - border-top-left-radius: 0; - -moz-border-radius-topleft: 0; - -webkit-border-top-left-radius: 0; -} -.overlay .ui-dialog-titlebar-close span { - display: none; -} -.overlay .ui-dialog-content { - color: #292929; - background-color: #f8f8f8; -} - -/** - * Overlay content. - */ -.overlay #overlay-container { - margin: 0; - padding: 0; - width: 100%; - overflow: visible; - background: #fff; -} -.overlay #overlay-element { - overflow: hidden; - width: 100%; + z-index: 500; height: 100%; + width: 100%; } -/** - * Tabs on the overlay. - */ -.overlay .ui-dialog-titlebar ul { - position: absolute; - right: 20px; - bottom: 0; - margin: 0; - line-height: 27px; - text-transform: uppercase; -} -.overlay .ui-dialog-titlebar ul li { - display: inline; - list-style: none; - margin: 0 0 0 -3px; - padding: 0; +.overlay-modal-background { + /* Using a transparent png renders faster than using opacity */ + background: transparent url(images/background.png) repeat; } -.overlay .ui-dialog-titlebar ul li a, -.overlay .ui-dialog-titlebar ul li a:active, -.overlay .ui-dialog-titlebar ul li a:visited, -.overlay .ui-dialog-titlebar ul li a:hover { - display: inline-block; - background-color: #a6a7a2; - border-radius: 8px 8px 0 0; - -moz-border-radius: 8px 8px 0 0; - -webkit-border-top-left-radius: 8px; - -webkit-border-top-right-radius: 8px; - color: #000; - font-weight: bold; - padding: 0 14px; - text-decoration: none; - font-size: 11px; - margin: 0; -} -.overlay .ui-dialog-titlebar ul li.active a, -.overlay .ui-dialog-titlebar ul li.active a.active, -.overlay .ui-dialog-titlebar ul li.active a:active, -.overlay .ui-dialog-titlebar ul li.active a:visited { - background-color: #fff; - margin: 0; -} -.overlay .ui-dialog-titlebar ul li a:hover { - color: #fff; -} -.overlay .ui-dialog-titlebar ul li.active a:hover { - color: #000; +.overlay-element { + z-index: 501; + background: transparent; + left: -200%; } - -/** - * Add to shortcuts link - */ -.overlay div.add-or-remove-shortcuts { - padding-top: 0.9em; +.overlay-element.overlay-active { + left: 0; } /** - * IE 6 Fix. * - * Use filter to support transparency in IE6 for the overlay background. */ -* html .ui-widget-overlay { - filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='modules/overlay/images/background.png', sizingMethod='scale'); - background: none; +.overlay-displace-top, +.overlay-displace-bottom { + z-index: 600; } Index: modules/overlay/overlay.module =================================================================== RCS file: /cvs/drupal/drupal/modules/overlay/overlay.module,v retrieving revision 1.17 diff -u -r1.17 overlay.module --- modules/overlay/overlay.module 24 Apr 2010 07:14:29 -0000 1.17 +++ modules/overlay/overlay.module 1 May 2010 15:38:28 -0000 @@ -46,6 +46,18 @@ } /** + * Implements hook_theme(). + */ +function overlay_theme() { + return array( + 'overlay' => array( + 'render element' => 'page', + 'template' => 'overlay', + ), + ); +} + +/** * Implements hook_init(). * * Determine whether the current page request is destined to appear in the @@ -150,8 +162,7 @@ $module_path . '/overlay-parent.css' => array(), ), 'dependencies' => array( - array('system', 'ui.dialog'), - array('system', 'ui.position'), + array('system', 'ui'), array('system', 'jquery-bbq'), ), ); @@ -163,8 +174,8 @@ 'js' => array( $module_path . '/overlay-child.js' => array(), ), - 'dependencies' => array( - array('system', 'ui'), + 'css' => array( + $module_path . '/overlay-child.css' => array(), ), ); @@ -210,6 +221,22 @@ } /** + * Implements hook_page_build(). + * + * Add admin toolbar to the page_top region automatically. + */ +function overlay_page_build(&$page) { + if (overlay_get_mode() == 'child') { + $page['overlay'] = array( + '#pre_render' => array('toolbar_pre_render'), + '#access' => user_access('access toolbar'), + 'toolbar_drawer' => array(), + ); + $page['overlay']['titlebar'] = array(); + } +} + +/** * Implements hook_page_alter(). */ function overlay_page_alter(&$page) { @@ -221,6 +248,11 @@ $page[$skipped_region]['#access'] = FALSE; } } + + if (overlay_get_mode() == 'child') { + // Add the overlay wrapper before the html wrapper. + array_unshift($page['#theme_wrappers'], 'overlay'); + } } /** @@ -284,6 +316,46 @@ } /** + * Process variables for overlay.tpl.php + * + * Prepare the values passed to the theme_block function to be passed + * into a pluggable template engine. Uses block properties to generate a + * series of template file suggestions. If none are found, the default + * block.tpl.php is used. + * + * Most themes utilize their own copy of block.tpl.php. The default is located + * inside "modules/block/block.tpl.php". Look in there for the full list of + * variables. + * + * The $variables array contains the following arguments: + * - $block + * + * @see overlay.tpl.php + */ +function template_preprocess_overlay(&$variables) { + $variables['tabs'] = menu_primary_local_tasks(); + $variables['title'] = drupal_get_title(); + + $variables['title_attributes_array']['tabindex'] = -1; + $variables['title_attributes_array']['unselectable'] = 'on'; +} + +/** + * Process variables for overlay.tpl.php + * + * Perform final addition and modification of variables before passing into + * the template. To customize these variables, call drupal_render() on elements + * in $variables['page'] during THEME_preprocess_page(). + * + * @see template_preprocess_overlay() + * @see overlay.tpl.php + */ +function template_process_overlay(&$variables) { + // Place the rendered HTML for the page body into a top level variable. + $variables['page'] = $variables['page']['#children']; +} + +/** * Preprocess template variables for page.tpl.php. * * Display breadcrumbs correctly inside the overlay. @@ -296,17 +368,10 @@ $overlay_breadcrumb = drupal_get_breadcrumb(); array_shift($overlay_breadcrumb); $variables['breadcrumb'] = theme('breadcrumb', array('breadcrumb' => $overlay_breadcrumb)); - } -} -/** - * Preprocess template variables for toolbar.tpl.php. - * - * Adding the 'overlay-displace-top' class to the toolbar pushes the overlay - * down, so it appears below the toolbar. - */ -function overlay_preprocess_toolbar(&$variables) { - $variables['classes_array'][] = "overlay-displace-top"; + $variables['tabs'] = ''; + $variables['primary_local_tasks'] = ''; + } } /** @@ -477,9 +542,6 @@ case 'child': drupal_add_library('overlay', 'child'); - // Pass child's document height on to parent document as quickly as - // possible so it can be updated accordingly. - drupal_add_js('if (parent.Drupal && parent.Drupal.overlay) { parent.Drupal.overlay.innerResize(jQuery(document.body).outerHeight()); }', array('type' => 'inline', 'scope' => 'footer')); // Allow modules to act upon overlay events. module_invoke_all('overlay_child_initialize'); Index: modules/overlay/overlay-parent.js =================================================================== RCS file: /cvs/drupal/drupal/modules/overlay/overlay-parent.js,v retrieving revision 1.40 diff -u -r1.40 overlay-parent.js --- modules/overlay/overlay-parent.js 30 Apr 2010 05:25:19 -0000 1.40 +++ modules/overlay/overlay-parent.js 1 May 2010 15:38:28 -0000 @@ -4,8 +4,6 @@ /** * Open the overlay, or load content into it, when an admin link is clicked. - * - * http://docs.jquery.com/Namespaced_Events */ Drupal.behaviors.overlayParent = { attach: function (context, settings) { @@ -15,17 +13,18 @@ } this.processed = true; - // Bind event handlers to the parent window. $(window) - // When the hash (URL fragment) changes, open the overlay if needed. - .bind('hashchange.overlay-event', Drupal.overlay.hashchangeHandler) - // Trigger the hashchange event once, after the page is loaded, so that - // permalinks open the overlay. - .trigger('hashchange.overlay-event'); - // Instead of binding a click event handler to every link we bind one to the - // document and only handle events that bubble up. This allows other scripts - // to bind their own handlers to links and also to prevent overlay's handling. - $(document).bind('click.overlay-event', Drupal.overlay.clickHandler); + // When the hash (URL fragment) changes, open the overlay if needed. + .bind('hashchange.drupal-overlay', Drupal.overlay.hashchangeHandler) + // Trigger the hashchange event once, after the page is loaded, so that + // permalinks open the overlay. + .trigger('hashchange.drupal-overlay'); + + $(document) + // Instead of binding a click event handler to every link we bind one to the + // document and only handle events that bubble up. This allows other scripts + // to bind their own handlers to links and also to prevent overlay's handling. + .bind('click.drupal-overlay, mouseup.drupal-overlay', Drupal.overlay.clickHandler); } }; @@ -44,224 +43,104 @@ * loading. */ Drupal.overlay = Drupal.overlay || { - options: {}, isOpen: false, isOpening: false, isClosing: false, isLoading: false, - resizeTimeoutID: null, - lastHeight: 0, - - $wrapper: null, - $dialog: null, - $dialogTitlebar: null, $container: null, - $iframe: null, + $iframeA: null, + $iframeB: null, - $iframeWindow: null, - $iframeDocument: null, - $iframeBody: null + iframeWindow: null }; +Drupal.overlay.prototype = {}; + /** - * Open an overlay. + * Open the overlay. * - * Ensure that only one overlay is opened ever. Use Drupal.overlay.load() if - * the overlay is already open but a new page needs to be opened. - * - * @param options - * Properties of the overlay to open: - * - url: the URL of the page to open in the overlay. - * - width: width of the overlay in pixels. - * - height: height of the overlay in pixels. - * - autoFit: boolean indicating whether the overlay should be resized to - * fit the contents of the document loaded. - * - customDialogOptions: an object with custom jQuery UI Dialog options. + * @param url + * The URL of the page to open in the overlay. * * @return * If the overlay was opened true, otherwise false. */ -Drupal.overlay.open = function (options) { - var self = this; - +Drupal.overlay.open = function (url) { // Just one overlay is allowed. - if (self.isOpen || self.isOpening) { - return false; + if (this.isOpen || this.isOpening) { + return this.load(url); } - self.isOpening = true; - - var defaultOptions = { - url: options.url, - width: options.width, - height: options.height, - autoFit: (options.autoFit == undefined || options.autoFit), - customDialogOptions: options.customDialogOptions || {} - }; - - self.options = $.extend(defaultOptions, options); + this.isOpening = true; // Create the dialog and related DOM elements. - self.create(); + this.create(); - // Open the dialog. - self.$container.dialog('open'); + this.isOpening = false; + this.isOpen = true; + $(document.documentElement).addClass('overlay-open'); // Allow other scripts to respond to this event. $(document).trigger('drupalOverlayOpen'); - return true; + return this.load(url); }; /** * Create the underlying markup and behaviors for the overlay. - * - * Reuses jQuery UI's dialog component to construct the overlay markup and - * behaviors, sanitizing the options previously set in self.options. */ Drupal.overlay.create = function () { var self = this; - var $window = $(window); - var $body = $('body'); - - var delayedOuterResize = function() { - setTimeout(self.outerResize, 1); - }; - // Open callback for jQuery UI Dialog. - var dialogOpen = function () { - // Unbind the keypress handler installed by ui.dialog itself. - // IE does not fire keypress events for some non-alphanumeric keys - // such as the tab character. http://www.quirksmode.org/js/keys.html - // Also, this is not necessary here because we need to deal with an - // iframe element that contains a separate window. - // We'll try to provide our own behavior from bindChild() method. - self.$dialog.unbind('keypress.ui-dialog'); - - // Add title to close button features for accessibility. - self.$dialogTitlebar.find('.ui-dialog-titlebar-close').attr('title', Drupal.t('Close')); - - // Replace the title span element with an h1 element for accessibility. - var $dialogTitle = self.$dialogTitlebar.find('.ui-dialog-title'); - $dialogTitle.replaceWith(Drupal.theme('overlayTitleHeader', $dialogTitle.html())); - - // Wrap the dialog into a div so we can center it using CSS. - self.$dialog.wrap(Drupal.theme('overlayWrapper')); - self.$wrapper = self.$dialog.parent(); - - self.$dialog.css({ - // Remove some CSS properties added by ui.dialog itself. - position: '', left: '', top: '', height: '' - }); + this.$container = $(Drupal.theme('overlayContainer')) + .appendTo(document.body); - // Add a class to the body to indicate the overlay is open. - $body.addClass('overlay-open'); + this.activeFrame = this.$iframeA = $(Drupal.theme('overlayElement')) + .appendTo(this.$container); - // Adjust overlay size when window is resized. - $window.bind('resize.overlay-event', delayedOuterResize); + this.inactiveFrame = this.$iframeB = $(Drupal.theme('overlayElement')) + .appendTo(this.$container); - if (self.options.autoFit) { - $body.addClass('overlay-autofit'); - } - else { - // Add scrollbar to the iframe when autoFit is disabled. - self.$iframe.css('overflow', 'auto').attr('scrolling', 'yes'); + var overlayLoad = function (event) { + var iframeDocument = this.contentDocument || this.contentWindow.document; + var iframeWindow = iframeDocument.defaultView || iframeDocument.parentWindow; + if (iframeDocument.location == 'about:blank') { + return; } - // Compute initial dialog size. - self.outerResize(); - - // Load the document on hidden iframe (see bindChild method). - self.load(self.options.url); + self.isLoading = false; + $(document.documentElement).removeClass('overlay-loading'); + event.data.sibling.removeClass('overlay-active'); + + // Only continue when overlay is still open and not closing. + if (self.isOpen && !self.isClosing) { + // And child document is an actual overlayChild. + if (iframeWindow.Drupal && iframeWindow.Drupal.overlayChild) { + self.activeFrame = $(this).addClass('overlay-active'); + self.inactiveFrame = event.data.sibling; - if ($.isFunction(self.options.onOverlayOpen)) { - self.options.onOverlayOpen(self); + // Allow other scripts to respond to this event. + $(document).trigger('drupalOverlayLoad'); + } + else { + self.redirect(window.location.href); + } } - - self.isOpen = true; - self.isOpening = false; - }; - - // Before close callback for jQuery UI Dialog. - var dialogBeforeClose = function () { - // Prevent double execution when close is requested more than once. - if (!self.isOpen || self.isClosing) { - return false; - } - - // Allow other scripts to decide if the overlay can be closed. If an event- - // handler returns false the overlay won't be closed. The external script - // should call Drupal.overlay.close() again when it is ready for closing. - var event = $.Event('drupalOverlayBeforeClose'); - $(document).trigger(event); - if (event.isDefaultPrevented()) { - return false; - } - - self.isClosing = true; - - // Stop all animations. - $window.unbind('resize.overlay-event', delayedOuterResize); - clearTimeout(self.resizeTimeoutID); - }; - - // Close callback for jQuery UI Dialog. - var dialogClose = function () { - $(document).unbind('keydown.overlay-event'); - - $body.removeClass('overlay-open').removeClass('overlay-autofit'); - - // When the iframe is still loading don't destroy it immediately but after - // the content is loaded (see self.load). - if (!self.isLoading) { - // As some browsers (webkit) fire a load event when the iframe is removed, - // load handlers need to be unbound before removing the iframe. - self.$iframe.unbind('load.overlay-event'); + else { self.destroy(); } - - self.isOpen = false; - self.isClosing = false; - - self.lastHeight = 0; - - // Allow other scripts to respond to this event. - $(document).trigger('drupalOverlayClose'); }; - // Default jQuery UI Dialog options. - var dialogOptions = { - autoOpen: false, - closeOnEscape: true, - dialogClass: 'overlay', - draggable: false, - modal: true, - resizable: false, - title: Drupal.t('Loading...'), - zIndex: 500, - - // When the width is not set, use an empty string instead, so that CSS will - // be able to handle it. - width: self.options.width || '', - height: self.options.height, - - open: dialogOpen, - beforeclose: dialogBeforeClose, - close: dialogClose - }; + this.$iframeA.bind('load.drupal-overlay', { sibling: this.$iframeB }, overlayLoad); + this.$iframeB.bind('load.drupal-overlay', { sibling: this.$iframeA }, overlayLoad); - // Create the overlay container and iframe. - self.$iframe = $(Drupal.theme('overlayElement')); - self.$container = $(Drupal.theme('overlayContainer')).append(self.$iframe); - - // Allow external script to override the default jQuery UI Dialog options. - $.extend(dialogOptions, self.options.customDialogOptions); - - // Create the jQuery UI Dialog. - self.$container.dialog(dialogOptions); - // Cache dialog selector. - self.$dialog = self.$container.parents('.' + dialogOptions.dialogClass); - self.$dialogTitlebar = self.$dialog.find('.ui-dialog-titlebar'); + $(window).bind('resize.drupal-overlay', this.outerResize); + $(document) + .bind('drupalOverlayLoad.drupal-overlay', this.outerResize) + .bind('drupalOverlayClose.drupal-overlay', function () { + $('.overlay-displace-top, .overlay-displace-bottom').css({maxWidth: '', clip: ''}); + }) + .bind('keydown.drupal-overlay', Drupal.overlay.keydownHandler); }; /** @@ -271,124 +150,81 @@ * already open. */ Drupal.overlay.load = function (url) { - var self = this; - var iframeElement = self.$iframe.get(0); - - self.isLoading = true; - - // Change the overlay title. - self.$container.dialog('option', 'title', Drupal.t('Loading...')); - // Remove any existing shortcut button markup in the title section. - self.$dialogTitlebar.find('.add-or-remove-shortcuts').remove(); - - // Remove any existing tabs in the title section, but only if requested url - // is not one of those tabs. If the latter, set that tab active. Only check - // for tabs when the overlay is not empty. - if (self.$iframeBody) { - var urlPath = self.getPath(url); - - // Get the primary tabs - var $tabs = self.$dialogTitlebar.find('ul'); - var $tabsLinks = $tabs.find('> li > a'); - - // Check if clicked on a primary tab - var $activeLink = $tabsLinks.filter(function () { return self.getPath(this) == urlPath; }); - - if ($activeLink.length) { - var active_tab = Drupal.t('(active tab)'); - $tabsLinks.parent().removeClass('active').find('element-invisible:contains(' + active_tab + ')').appendTo($activeLink); - $activeLink.parent().addClass('active'); - removeTabs = false; - } - else { - // Get the secondary tabs - var $secondary = self.$iframeBody.find('ul.secondary'); - var $secondaryLinks = $secondary.find('> li > a'); - - // Check if clicked on a secondary tab - var $activeLinkSecondary = $secondaryLinks.filter(function () { return self.getPath(this) == urlPath; }); - - if ($activeLinkSecondary.length) { - var active_tab = Drupal.t('(active tab)'); - $secondaryLinks.parent().removeClass('active').find('element-invisible:contains(' + active_tab + ')').appendTo($activeLinkSecondary); - $activeLinkSecondary.parent().addClass('active'); - removeTabs = false; - } - else { - $tabs.remove(); - } - } + if (!this.isOpen) { + return false; } - self.$iframeWindow = null; - self.$iframeDocument = null; - self.$iframeBody = null; - - // No need to resize while loading. - clearTimeout(self.resizeTimeoutID); - // Allow other scripts to respond to this event. $(document).trigger('drupalOverlayBeforeLoad'); - // While the overlay is loading, we remove the loaded class from the dialog. - // After the loading is finished, the loaded class is added back. The loaded - // class is being used to hide the iframe while loading. - // See overlay-parent.css .overlay-loaded #overlay-element. - self.$dialog.removeClass('overlay-loaded'); - self.$iframe.once('overlay-event-load') - .bind('load.overlay-event', function () { - self.isLoading = false; - - // Only continue when overlay is still open and not closing. - if (self.isOpen && !self.isClosing) { - self.$dialog.addClass('overlay-loaded'); - - // Allow other scripts to respond to this event. - $(document).trigger('drupalOverlayLoad'); - } - else { - self.destroy(); - } - }); + $(document.documentElement).addClass('overlay-loading'); - // Get the document object of the iframe window. - // See http://xkr.us/articles/dom/iframe-document/. - var iframeDocument = (iframeElement.contentWindow || iframeElement.contentDocument); - if (iframeDocument.document) { - iframeDocument = iframeDocument.document; - } + var iframeElement = this.inactiveFrame[0]; + // The contentDocument property is not supported in IE until IE8. + var iframeDocument = iframeElement.contentDocument || iframeElement.contentWindow.document; // location.replace doesn't create a history entry. location.href does. // In this case, we want location.replace, as we're creating the history // entry using URL fragments. iframeDocument.location.replace(url); + + return true; }; /** * Close the overlay and remove markup related to it from the document. + * + * @return + * If the overlay was closed true, otherwise false. */ Drupal.overlay.close = function () { - return this.$container.dialog('close'); + // Prevent double execution when close is requested more than once. + if (!this.isOpen || this.isClosing) { + return false; + } + + // Allow other scripts to respond to this event. + var event = $.Event('drupalOverlayBeforeClose'); + $(document).trigger(event); + // If a handler returned false, the close will be prevented. + if (event.isDefaultPrevented()) { + return false; + } + + this.isClosing = true; + + // When the iframe is still loading don't destroy it immediately but after + // the content is loaded (see self.load). + if (!this.isLoading) { + this.destroy(); + } + + this.isOpen = false; + $(document.documentElement).removeClass('overlay-open'); + + // Allow other scripts to respond to this event. + $(document).trigger('drupalOverlayClose'); + + if (!this.isLoading) { + this.isClosing = false; + } + + return true; }; /** * Destroy the overlay. */ Drupal.overlay.destroy = function () { - var self = this; + this.$iframeA.unbind('.drupal-overlay'); + this.$iframeB.unbind('.drupal-overlay'); + this.$container.remove(); + + this.$container = null; + this.$iframeA = null; + this.$iframeB = null; - self.$container.dialog('destroy').remove(); - self.$wrapper.remove(); - - self.$wrapper = null; - self.$dialog = null; - self.$dialogTitlebar = null; - self.$container = null; - self.$iframe = null; - - self.$iframeWindow = null; - self.$iframeDocument = null; - self.$iframeBody = null; + this.iframeWindow = null; }; /** @@ -405,7 +241,7 @@ // If the link is already open, force the hashchange event to simulate reload. if (location.href == link) { - $(window).trigger('hashchange.overlay-event'); + $(window).trigger('hashchange.drupal-overlay'); } location.href = link; @@ -414,174 +250,20 @@ /** * Bind the child window. - * - * Add tabs on the overlay, keyboard actions and display animation. */ Drupal.overlay.bindChild = function (iframeWindow, isClosing) { - var self = this; - self.$iframeWindow = iframeWindow.jQuery; - self.$iframeDocument = self.$iframeWindow(iframeWindow.document); - self.$iframeBody = self.$iframeWindow('body'); + this.iframeWindow = iframeWindow; // We are done if the child window is closing. - if (isClosing || self.isClosing || !self.isOpen) { + if (isClosing || this.isClosing || !this.isOpen) { return; } // Make sure the parent window URL matches the child window URL. - self.syncChildLocation(iframeWindow.document.location); + this.syncChildLocation(iframeWindow.document.location); - // Unbind the mousedown handler installed by ui.dialog because the - // handler interferes with use of the scroll bar in Chrome & Safari. - // After unbinding from the document we bind a handler to the dialog overlay - // which returns false to prevent event bubbling. - // See http://dev.jqueryui.com/ticket/4671. - // See https://bugs.webkit.org/show_bug.cgi?id=19033. - // Do the same for the click handler as prevents default handling of clicks in - // displaced regions (e.g. opening a link in a new browser tab when CTRL was - // pressed while clicking). - $(document).unbind('mousedown.dialog-overlay click.dialog-overlay'); - $('.ui-widget-overlay').bind('mousedown.dialog-overlay click.dialog-overlay', function (){return false;}); - - // Unbind the keydown and keypress handlers installed by ui.dialog because - // they interfere with use of browser's keyboard hotkeys like CTRL+w. - // This may cause problems when using modules that implement keydown or - // keypress handlers as they aren't blocked when overlay is open. - $(document).unbind('keydown.dialog-overlay keypress.dialog-overlay'); - - // Reset the scroll to the top of the window so that the overlay is visible again. - window.scrollTo(0, 0); - - var iframeTitle = self.$iframeDocument.attr('title'); - - // Update the dialog title with the child window title. - self.$container.dialog('option', 'title', iframeTitle); - self.$dialogTitlebar.find('.ui-dialog-title').focus(); // Add a title attribute to the iframe for accessibility. - self.$iframe.attr('title', Drupal.t('@title dialog', { '@title': iframeTitle })); - - // Remove any existing shortcut button markup in the title section. - self.$dialogTitlebar.find('.add-or-remove-shortcuts').remove(); - // If the shortcut add/delete button exists, move it to the dialog title. - var $addToShortcuts = self.$iframeWindow('.add-or-remove-shortcuts'); - if ($addToShortcuts.length) { - // Move the button markup to the title section. We need to copy markup - // instead of moving the DOM element, because Webkit and IE browsers will - // not move DOM elements between two DOM documents. - $addToShortcuts = $(self.$iframeWindow('