Index: misc/tableheader.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableheader.js,v retrieving revision 1.26 diff -u -p -u -p -r1.26 tableheader.js --- misc/tableheader.js 15 Sep 2009 20:50:48 -0000 1.26 +++ misc/tableheader.js 18 Sep 2009 11:35:04 -0000 @@ -18,8 +18,9 @@ Drupal.behaviors.tableHeader = { var headers = []; $('table.sticky-enabled thead', context).once('tableheader', function () { - // Clone thead so it inherits original jQuery properties. - var headerClone = $(this).clone(true).insertBefore(this.parentNode).wrap('').parent().css({ + // Clone thead so it inherits original jQuery properties. Hide the table + // to avoid a flash of the header clone upon page load. + var headerClone = $(this).clone(true).hide().insertBefore(this.parentNode).wrap('').parent().css({ position: 'fixed', top: '0px' }); @@ -32,6 +33,9 @@ Drupal.behaviors.tableHeader = { headerClone.table = table; // Finish initializing header positioning. tracker(headerClone); + // We hid the header to avoid it showing up erroneously on page load; + // we need to unhide it now so that it will show up when expected. + $(headerClone).children('thead').show(); $(table).addClass('sticky-table'); }); Index: modules/locale/locale.test =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v retrieving revision 1.40 diff -u -p -u -p -r1.40 locale.test --- modules/locale/locale.test 28 Aug 2009 14:40:12 -0000 1.40 +++ modules/locale/locale.test 18 Sep 2009 11:35:04 -0000 @@ -236,7 +236,7 @@ class LocaleTranslationFunctionalTest ex $this->clickLink(t('edit')); // We save the lid from the path. $matches = array(); - preg_match('!admin/config/regional/translate/edit/(\d)+!', $this->getUrl(), $matches); + preg_match('!admin/config/regional/translate/edit/(\d+)!', $this->getUrl(), $matches); $lid = $matches[1]; // No t() here, it's surely not translated yet. $this->assertText($name, t('name found on edit screen.')); Index: modules/node/node.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v retrieving revision 1.67 diff -u -p -u -p -r1.67 node.admin.inc --- modules/node/node.admin.inc 18 Sep 2009 00:12:47 -0000 1.67 +++ modules/node/node.admin.inc 18 Sep 2009 11:35:05 -0000 @@ -447,6 +447,9 @@ function node_admin_nodes() { foreach ($result as $node) { $nodes[$node->nid] = ''; $options = empty($node->language) ? array() : array('language' => $languages[$node->language]); + // Set a class to flag to the overlay, if present, not to open the link in + // the overlay. + $options['attributes']['class'] = 'overlay-escape'; $form['title'][$node->nid] = array('#markup' => l($node->title, 'node/' . $node->nid, $options) . ' ' . theme('mark', node_mark($node->nid, $node->changed))); $form['name'][$node->nid] = array('#markup' => check_plain(node_type_get_name($node))); $form['username'][$node->nid] = array('#markup' => theme('username', $node)); Index: modules/overlay/overlay-child.js =================================================================== RCS file: modules/overlay/overlay-child.js diff -N modules/overlay/overlay-child.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/overlay/overlay-child.js 18 Sep 2009 11:35:05 -0000 @@ -0,0 +1,157 @@ +// $Id: child.js,v 1.1.4.3 2009/06/17 15:16:26 markuspetrux Exp $ + +(function ($) { + +/** + * Overlay object for child windows. + */ +Drupal.overlayChild = Drupal.overlayChild || { processed: false, behaviors: {} }; + +/** + * Drupal will automatically attach the child dialog behavior to new content. + */ +Drupal.behaviors.overlayChild = { + attach: function(context, settings) { + Drupal.overlayChild.attachBehavior(context, settings); + } +}; + +/** + * Attach child dialog behavior. + */ +Drupal.overlayChild.attachBehavior = function(context, settings) { + var self = Drupal.overlayChild; + var settings = settings.overlayChild || {}; + + // Make sure this behavior is not processed more than once. + if (self.processed) { + return; + } + self.processed = true; + + // If we cannot reach the parent window, then we have nothing else to do + // here. + if (!self.isObject(parent.Drupal) || !self.isObject(parent.Drupal.overlay)) { + return; + } + + // 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) { + parent.Drupal.overlay.skipWarning = true; + parent.Drupal.overlay.bindChild(window, true); + // Close the child window from a separate thread because the current + // one is busy processing Drupal behaviors. + setTimeout(function() { + // We need to store the parent variable locally because it will + // disappear as soon as we close the iframe. + var p = parent; + p.Drupal.overlay.close(settings.statusMessages); + if (typeof settings.redirect == 'string') { + p.Drupal.overlay.redirect(settings.redirect); + } + }, 1); + return; + } + + // Ok, now we can tell the parent window we're ready. + parent.Drupal.overlay.bindChild(window); + + // Install onBeforeUnload callback, if module is present. + if (self.isObject(Drupal.onBeforeUnload) && !Drupal.onBeforeUnload.callbackExists('overlayChild')) { + Drupal.onBeforeUnload.addCallback('overlayChild', function() { + // Tell the parent window we're unloading. + parent.Drupal.overlay.unbindChild(window); + }); + } + + // Attach child related behaviors to the iframe document. + self.attachBehaviors(context, settings); +}; + +/** + * Add the isObject() method to the overlayChild object for convenience. + */ +Drupal.overlayChild.isObject = parent.Drupal.overlay.isObject; + +/** + * Attach child related behaviors to the iframe document. + */ +Drupal.overlayChild.attachBehaviors = function(context, settings) { + $.each(this.behaviors, function() { + this(context, settings); + }); +}; + +/** + * Scroll to the top of the page. + * + * This makes the overlay visible to users even if it is not as tall as the + * previously shown overlay was. + */ +Drupal.overlayChild.behaviors.scrollToTop = function(context, settings) { + window.scrollTo(0, 0); +}; + +/** + * Modify links and forms depending on their relation to the overlay. + * + * By default, forms and links are assumed to keep the flow in the overlay. + * Thus their action and href attributes respectively get a ?render=overlay + * suffix. Links having the .overlay-escape class should however close the + * overlay and redirect the parent page to the given link. Such are links + * in a content listing, where administration options are mixed with links + * to the actual content to be shown on the site out of the overlay. + */ +Drupal.overlayChild.behaviors.parseLinks = function(context, settings) { + $('a:not(.overlay-exclude)', context).once('overlay').each(function() { + // Links that have the class "overlay-escape" should close the overlay and + // open in the main window. + if ($(this).hasClass('overlay-escape')) { + $(this).click(function() { + // We need to store the parent variable locally because it will + // disappear as soon as we close the iframe. + var parentWindow = parent; + if (parentWindow.Drupal.overlay.close(false)) { + parentWindow.Drupal.overlay.redirect($(this).attr('href')); + } + return false; + }); + return; + } + // Obtain the href attribute of the link. + var href = $(this).attr('href'); + // Do not process links with an empty href, or that only have the fragment. + if (href.length <= 0 || href.charAt(0) == '#') { + return; + } + if (href.indexOf('http') != 0 && href.indexOf('https') != 0) { + // Keep internal linked pages in the overlay. + var fragmentIndex = href.indexOf('#'); + var fragment = ''; + if (fragmentIndex != -1) { + var fragment = href.substr(fragmentIndex); + href = href.substr(0, fragmentIndex); + } + href += (href.indexOf('?') > -1 ? '&' : '?') + 'render=overlay' + fragment; + $(this).attr('href', href); + } + else { + $(this).attr('target', '_new'); + } + }); + $('form:not(.overlay-processed)', context).addClass('overlay-processed').each(function() { + // Obtain the action attribute of the form. + var action = $(this).attr('action'); + if (action.indexOf('http') != 0 && action.indexOf('https') != 0) { + // Keep internal forms in the overlay. + action += (action.indexOf('?') > -1 ? '&' : '?') + 'render=overlay'; + $(this).attr('action', action); + } + else { + $(this).attr('target', '_new'); + } + }); +}; + +})(jQuery); Index: modules/overlay/overlay-parent.css =================================================================== RCS file: modules/overlay/overlay-parent.css diff -N modules/overlay/overlay-parent.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/overlay/overlay-parent.css 18 Sep 2009 11:35:05 -0000 @@ -0,0 +1,137 @@ +/* $Id$ */ + +/** + * jQuery UI Dialog classes. + */ +.overlay { + color: #000; + padding-right: 42px; +} + +.overlay .ui-dialog-titlebar { + position: relative; + height: 35px; + white-space: nowrap; + z-index: 2; + padding: 0 20px; +} + +.overlay .ui-dialog-title { + display: block; + font-family: Verdana,sans-serif; + position: absolute; + top: 0; + left: 20px; + margin: 0.3em 0; + padding: 0; + color: #fff; + font-size: 20px; +} + +.overlay .ui-dialog-title:active, +.overlay .ui-dialog-title:focus { + outline: 0; +} + +.overlay .ui-dialog-titlebar-close { + display: block; + position: absolute; + right: -31px; + top: 35px; + margin: 0; + padding: 0; + width: 32px; + height: 36px; + background: transparent url(images/close.png) no-repeat; +} + +.overlay .ui-dialog-titlebar-close span { + display: none; +} + +.overlay .ui-dialog-content { + color: #292929; + background-color: #f8f8f8; +} + +/** + * ui-dialog overlay. + */ +.ui-widget-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0.7; + filter: alpha(opacity=80); +} + +/** + * Overlay content and shadows. + */ +#overlay-container { + margin: 0; + padding: 0; + background: #fff url(images/loading.gif) no-repeat 50% 50%; + -webkit-box-shadow: 8px 8px 8px rgba(0,0,0,.5); + -moz-box-shadow: 8px 8px 8px rgba(0,0,0,.5); + box-shadow: 8px 8px 8px rgba(0,0,0,.5); +} + +#overlay-element { + margin: 0; + padding: 0; + border: none; + overflow: hidden; +} + +/** + * Tabs on the overlay. + */ +.ui-dialog-titlebar ul { + float: right; + margin: 0 0 -10px 0; + padding: 3px 0 0 8px; + line-height: 40px; + text-transform: uppercase; + font-size: 12px; +} + +.ui-dialog-titlebar ul li { + display: inline; + list-style: none; + margin-left: 0; +} + +.ui-dialog-titlebar ul li a, +.ui-dialog-titlebar ul li a:active, +.ui-dialog-titlebar ul li a:visited, +.ui-dialog-titlebar ul li a:hover { + background-color: #a6a7a2; + -moz-border-radius: 8px 8px 0 0; + -webkit-border-top-left-radius: 8px; + -webkit-border-top-right-radius: 8px; + border-radius: 8px 8px 0 0; + color: #000; + font-weight: bold; + padding: 8px 20px 3px 20px; + text-decoration: none; +} + +.ui-dialog-titlebar ul li.active a, +.ui-dialog-titlebar ul li.active a.active, +.ui-dialog-titlebar ul li.active a:active, +.ui-dialog-titlebar ul li.active a:visited { + background-color: #fff; + padding: 8px 20px 5px 20px; +} + +.ui-dialog-titlebar ul li a:hover { + color: #fff; +} + +.ui-dialog-titlebar ul li.active a:hover { + color: #000; +} Index: modules/overlay/overlay-parent.js =================================================================== RCS file: modules/overlay/overlay-parent.js diff -N modules/overlay/overlay-parent.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/overlay/overlay-parent.js 18 Sep 2009 11:35:05 -0000 @@ -0,0 +1,621 @@ +// $Id: parent.js,v 1.1.4.4 2009/06/19 15:32:57 markuspetrux Exp $ + +(function ($) { + +/** + * Open or modify overlay based on clicks of links marked with .to-overlay. + */ +Drupal.behaviors.overlayParent = { + attach: function(context, settings) { + + // Attach on the .to-overlay class. + $('a.to-overlay:not(.overlay-exclude)').once('overlay').click(function() { + + // Remove the active class from where it was, and add the active class to + // this link, so the button keeps highlighting where we are. Only + // highlight active items in the shortcuts bar. + $('#toolbar a').each(function() { + $(this).removeClass('active'); + }); + if ($(this).parents('div.toolbar-shortcuts').length) { + $(this).addClass('active'); + } + + // Append render variable, so the server side can choose the right + // rendering and add child modal frame code to the page if needed. + var linkURL = $(this).attr('href'); + linkURL += (linkURL.indexOf('?') > -1 ? '&' : '?') + 'render=overlay'; + + // If the modal frame is already open, replace the loaded document with + // this new one. Keeps browser history. + if (Drupal.overlay.isOpen) { + Drupal.overlay.load(linkURL); + return false; + } + + // There is overlay opened yet, we should open a new one. + var toolbarHeight = $('#toolbar').height(); + var overlayOptions = { + url: linkURL, + width: $(window).width() - 40, + height: $(window).height() - 40 - toolbarHeight, + // Remove active class from all header buttons. + onOverlayClose: function() { $('#toolbar a').each(function() { $(this).removeClass('active'); }); }, + draggable: false + }; + Drupal.overlay.open(overlayOptions); + + // Set position and styling to let the admin toolbar work. + $('.overlay').css('top', toolbarHeight + 20); + $('#toolbar').css('z-index', 2000); + + // Prevent default action of the link click event. + return false; + }); + } +}; + +/** + * Overlay object for parent windows. + */ +Drupal.overlay = Drupal.overlay || { + options: {}, + iframe: { $container: null, $element: null }, + isOpen: false +}; + +/** + * Open an 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 + * - onOverlayClose: callback to invoke when the overlay is closed + * @return + * If the overlay was opened true, otherwise false. + */ +Drupal.overlay.open = function(options) { + var self = this; + + // Just one overlay is allowed. + if (self.isOpen || $('#overlay-container').size()) { + return false; + } + + var defaultOptions = { + url: options.url, + width: options.width, + height: options.height, + autoFit: (options.autoFit == undefined || options.autoFit), + onOverlayClose: options.onOverlayClose + } + + self.options = $.extend(defaultOptions, options); + + // Create the dialog and related DOM elements. + self.create(); + + // Open the dialog offscreen where we can set its size, etc. + self.iframe.$container.dialog('option', { position: ['-999em', '-999em'] }).dialog('open'); + + return true; +}; + +/** + * 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; + + // Note: We use scrolling="yes" for IE as a workaround to yet another IE bug + // where the horizontal scrollbar is always rendered no matter how wide the + // iframe element is defined. + self.iframe.$element = $('