Index: misc/tableheader.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableheader.js,v retrieving revision 1.25 diff -u -r1.25 tableheader.js --- misc/tableheader.js 31 Aug 2009 05:51:08 -0000 1.25 +++ misc/tableheader.js 10 Sep 2009 23:05:14 -0000 @@ -18,8 +18,9 @@ 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 @@ 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 -r1.40 locale.test --- modules/locale/locale.test 28 Aug 2009 14:40:12 -0000 1.40 +++ modules/locale/locale.test 10 Sep 2009 23:05:14 -0000 @@ -236,7 +236,7 @@ $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.65 diff -u -r1.65 node.admin.inc --- modules/node/node.admin.inc 5 Sep 2009 06:53:01 -0000 1.65 +++ modules/node/node.admin.inc 10 Sep 2009 23:05:14 -0000 @@ -447,6 +447,9 @@ 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/toolbar/toolbar.module =================================================================== RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.module,v retrieving revision 1.10 diff -u -r1.10 toolbar.module --- modules/toolbar/toolbar.module 5 Sep 2009 15:05:05 -0000 1.10 +++ modules/toolbar/toolbar.module 10 Sep 2009 23:05:15 -0000 @@ -36,12 +36,30 @@ * Add admin toolbar to the page_top region automatically. */ function toolbar_page_build(&$page) { - if (user_access('access toolbar')) { + if (user_access('access toolbar') && toolbar_enabled()) { $page['page_top']['toolbar'] = toolbar_build(); } } /** + * Enable or disable the toolbar, or find out the current status of the + * toolbar (enabled or disabled). + * + * @param $enabled + * If given, will change the display mode of the toolbar to the given + * boolean. + * @return + * The current status of the toolbar, TRUE for enabled, FALSE for disabled. + */ +function toolbar_enabled($enabled = NULL) { + $setting = &drupal_static(__FUNCTION__, TRUE); + if (isset($enabled)) { + $setting = $enabled; + } + return $setting; +} + +/** * Implement hook_preprocess_page(). * * Add some page classes, so global page theming can adjust to the toolbar. Index: profiles/default/default.info =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.info,v retrieving revision 1.4 diff -u -r1.4 default.info --- profiles/default/default.info 30 Aug 2009 06:02:08 -0000 1.4 +++ profiles/default/default.info 10 Sep 2009 23:05:15 -0000 @@ -14,6 +14,7 @@ dependencies[] = dblog dependencies[] = search dependencies[] = toolbar +dependencies[] = overlay dependencies[] = field_ui dependencies[] = file files[] = default.profile Index: profiles/default/default.install =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.install,v retrieving revision 1.2 diff -u -r1.2 default.install --- profiles/default/default.install 27 Aug 2009 20:25:29 -0000 1.2 +++ profiles/default/default.install 10 Sep 2009 23:05:15 -0000 @@ -210,5 +210,4 @@ ->condition('name', 'seven') ->execute(); variable_set('admin_theme', 'seven'); - variable_set('node_admin_theme', '1'); } Index: themes/garland/style.css =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/style.css,v retrieving revision 1.64 diff -u -r1.64 style.css --- themes/garland/style.css 31 Aug 2009 17:40:03 -0000 1.64 +++ themes/garland/style.css 10 Sep 2009 23:05:15 -0000 @@ -508,6 +508,15 @@ font-size: 1.5em; } +/* Don't display any header elements when within the overlay, and adjust the page height accordingly. */ +body.overlay #header * { + display: none; +} + +body.overlay { + margin-top: -80px; +} + #wrapper #container #header h1 a:hover { text-decoration: none; } Index: themes/seven/style.css =================================================================== RCS file: /cvs/drupal/drupal/themes/seven/style.css,v retrieving revision 1.17 diff -u -r1.17 style.css --- themes/seven/style.css 5 Sep 2009 06:07:58 -0000 1.17 +++ themes/seven/style.css 10 Sep 2009 23:05:15 -0000 @@ -55,7 +55,7 @@ */ #branding { overflow: hidden; - padding: 20px 40px 0 40px; + padding: 20px 20px 0 20px; position: relative; background-color: #e0e0d8; } @@ -158,7 +158,7 @@ /** * Console. */ -#page .console { +#console { border-top: 1px solid #ccc; padding: 9px 0 10px; } @@ -261,7 +261,7 @@ } #block-system-main { - padding: 20px 0; + padding-bottom: 20px; background: #fff; color: #333; } @@ -611,9 +611,14 @@ ul.action-links { margin: 1em 0; + padding: 0 20px 0 20px; overflow: hidden; } +#block-system-main ul.action-links { + padding: 0; +} + ul.action-links li { float: left; margin: 0 1em 0 0; @@ -713,18 +718,27 @@ background: #fff; } -body.overlay #branding, -body.overlay #page-title, +body.overlay .primary, +body.overlay .page-title, body.overlay #page #left, body.overlay #page #footer { display: none; } +/* Branding needs a white background to look good in the overlay. */ +body.overlay #branding { + background-color: #ffffff; +} + +body.overlay #branding { + padding-top: 5px; +} + body.overlay #page { margin: 0; padding: 0; } -body.overlay #block-system-main { +body.overlay #content { padding: 20px; } --- overlay-child.js +++ overlay-child.js @@ -0,0 +1,148 @@ +// $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 iframed document. + */ +Drupal.overlayChild.attachBehaviors = function(context, settings) { + $.each(this.behaviors, function() { + this(context, settings); + }); +}; + +/** + * Scroll to the top of the page so that we don't get weird positioning errors + * in some browsers. + */ +Drupal.overlayChild.behaviors.scrollToTop = function(context, settings) { + window.scrollTo(0, 0); +}; + +/** + * Add target="_new" to all external URLs. + */ +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); --- overlay-parent.css +++ overlay-parent.css @@ -0,0 +1,139 @@ +/* $Id$ */ + +/** + * jQuery UI Dialog classes. + */ +.overlay { + color: #000; + padding-right: 42px; +} + +.overlay .ui-dialog-titlebar { + position: relative; + height: 30px; + white-space: nowrap; + z-index: 2; + padding-right: 20px; +} + +.overlay .ui-dialog-title { + display: block; + font-family: Verdana,sans-serif; + position: absolute; + top: 0; + left: 0; + margin: 0.2em 0.5em; + 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: -26px; + top: 30px; + margin: 0; + padding: 0; + width: 26px; + height: 26px; + background: transparent url(images/close.png) no-repeat; + -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); + -moz-border-radius: 0 13px 13px 0; + -webkit-border-top-left-radius: 8px; + -webkit-border-top-right-radius: 8px; + border-radius: 8px 8px 0 0; +} + +.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: 30px; + 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; --- overlay-parent.js +++ overlay-parent.js @@ -0,0 +1,557 @@ +// $Id: parent.js,v 1.1.4.4 2009/06/19 15:32:57 markuspetrux Exp $ + +(function ($) { + +Drupal.behaviors.keepOverlay = { + 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. + */ +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(options); + + // 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 overlay. + */ +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 = $('