From 23b32499e88e1548431b331b701e4a6f13015d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?"J.=20Rene=CC=81e=20Beach"?= Date: Mon, 15 Jul 2013 15:38:24 -0400 Subject: [PATCH] Issue #1847314: Reduce the dependency on JavaScript for the toolbar to display properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: J. ReneĢe Beach --- core/modules/contextual/contextual.toolbar.js | 2 +- core/modules/contextual/css/contextual.toolbar.css | 12 +- core/modules/toolbar/css/toolbar.module.css | 311 +++++++++----------- core/modules/toolbar/css/toolbar.theme.css | 8 +- core/modules/toolbar/js/toolbar.js | 94 ++++-- core/modules/toolbar/toolbar.module | 1 - core/modules/tour/css/tour.module.css | 12 +- 7 files changed, 222 insertions(+), 218 deletions(-) diff --git a/core/modules/contextual/contextual.toolbar.js b/core/modules/contextual/contextual.toolbar.js index ecd19d92..8a1ece7 100644 --- a/core/modules/contextual/contextual.toolbar.js +++ b/core/modules/contextual/contextual.toolbar.js @@ -26,7 +26,7 @@ function initContextualToolbar (context) { var model = contextualToolbar.model = new contextualToolbar.Model(); var viewOptions = $.extend({ - el: $('.js .toolbar .bar .contextual-toolbar-tab'), + el: $('.toolbar .bar .contextual-toolbar-tab'), model: model }, options); new contextualToolbar.VisualView(viewOptions); diff --git a/core/modules/contextual/css/contextual.toolbar.css b/core/modules/contextual/css/contextual.toolbar.css index 809f6a3..c6fc64e 100644 --- a/core/modules/contextual/css/contextual.toolbar.css +++ b/core/modules/contextual/css/contextual.toolbar.css @@ -13,13 +13,13 @@ } /* Tab appearance. */ -.js .toolbar .bar .contextual-toolbar-tab.tab { +.toolbar .bar .contextual-toolbar-tab.tab { float: right; /* LTR */ } -.js[dir="rtl"] .toolbar .bar .contextual-toolbar-tab.tab { +[dir="rtl"] .toolbar .bar .contextual-toolbar-tab.tab { float: left; } -.js .toolbar .bar .contextual-toolbar-tab button { +.toolbar .bar .contextual-toolbar-tab button { padding-bottom: 1em; padding-top: 1em; /* Hide tab text. */ @@ -27,10 +27,10 @@ text-indent: -9999px; line-height: 1em; } -.js[dir="rtl"] .toolbar .bar .contextual-toolbar-tab button { +[dir="rtl"] .toolbar .bar .contextual-toolbar-tab button { padding-right: 1.3333em; } -.js .toolbar .bar .contextual-toolbar-tab button.active { +.toolbar .bar .contextual-toolbar-tab button.active { background-image:-moz-linear-gradient(rgb(78,159,234) 0%,rgb(69,132,221) 100%); background-image:-webkit-gradient(linear,color-stop(0, rgb(78,159,234)),color-stop(1, rgb(69,132,221))); background-image: -webkit-linear-gradient(top, rgb(78,159,234) 0%, rgb(69,132,221) 100%); @@ -38,6 +38,6 @@ } /* @todo get rid of this declaration by making toolbar.module's CSS less specific */ -.js .toolbar .bar .contextual-toolbar-tab.tab.hidden { +.toolbar .bar .contextual-toolbar-tab.tab.hidden { display: none; } diff --git a/core/modules/toolbar/css/toolbar.module.css b/core/modules/toolbar/css/toolbar.module.css index f193d58..b139b03 100644 --- a/core/modules/toolbar/css/toolbar.module.css +++ b/core/modules/toolbar/css/toolbar.module.css @@ -5,30 +5,20 @@ * Aggressive resets so we can achieve a consistent look in hostile CSS * environments. */ -html.js #toolbar-administration, -html .toolbar * { +#toolbar-administration, +#toolbar-administration * { -moz-box-sizing: border-box; -o-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - margin: 0; - padding: 0; - vertical-align: baseline; } -html.js #toolbar-administration { +#toolbar-administration { font-size: small; line-height: 1; + margin: 0; + padding: 0; + vertical-align: baseline; } -html.js .toolbar { - left: 0; /* LTR */ - position: absolute; - top: 0; - width: 100%; -} -html.js[dir="rtl"] .toolbar { - left: auto; - right: 0; - } /** * Very specific overrides for Drupal system CSS. @@ -44,239 +34,210 @@ html.js[dir="rtl"] .toolbar { .toolbar .menu li { padding-top: 0; } -.js .toolbar .bar .tab, -.js .toolbar .menu li { +.toolbar .bar .tab, +.toolbar .menu li { display: block; } -.js .toolbar .bar .tab, -.js .toolbar .horizontal .tab { - float: left; /* LTR */ -} -.js[dir="rtl"] .toolbar .bar .tab, -.js[dir="rtl"] .toolbar .horizontal .tab { - float: right; -} -.js .toolbar a { +.toolbar a { display: block; line-height: 1; } + /** * Administration menu. */ -.js .toolbar .bar { - left: 0; /* LTR */ - position: absolute; - top: 0; +.toolbar .bar, +.toolbar .tray { + position: relative; z-index: 1250; - width: 100%; } -.js[dir="rtl"] .toolbar .bar { - left: auto; +/* Position the admin toolbar absolutely when the configured standard breakpoint + * is active. The toolbar container, that contains the bar and the trays, is + * position absolutely so that it scrolls with the page. Otherwise, on smaller + * screens, the components of the admin toolbar are positioned statically. */ +body.toolbar-paneled .toolbar-oriented, +.toolbar-oriented .bar, +.toolbar-oriented .tray { + left: 0; + position: absolute; right: 0; + top: 0; +} +/* Layer the bar just above the trays and above contextual link triggers. */ +.toolbar-oriented .bar { + z-index: 502; +} +/* Position the admin toolbar fixed when the configured standard breakpoint is + * active. */ +body.toolbar-paneled .toolbar-oriented .bar { + position: fixed; } +/* When the configured narrow breakpoint is active, the toolbar is sized to wrap + * around the trays in order to provide a context for scrolling tray content + * that is taller than the viewport. */ +body.toolbar-tray-open.toolbar-paneled.toolbar-vertical .toolbar-oriented { + bottom: 0; + width: 240px; + width: 15rem; +} +/* Present the admin toolbar tabs horizontally as a default on user agents that + * do not understand media queries or on user agents where JavaScript is + * disabled. */ +.toolbar .bar .tab, +.toolbar.horizontal li { + float: left; /* LTR */ +} +[dir="rtl"] .toolbar .bar .tab, +[dir="rtl"] .toolbar.horizontal li { + float: right; +} +/* Present the admin toolbar tabs vertically by default on user agents that + * that understand media queries. This will be the small screen default. */ @media only screen { - .js .toolbar .bar .tab, - .js .toolbar .tray li { + .toolbar .bar .tab, + .toolbar.horizontal li { float: none; /* LTR */ } - .js[dir="rtl"] .toolbar .bar .tab, - .js[dir="rtl"] .toolbar .tray li { + [dir="rtl"] .toolbar .bar .tab, + [dir="rtl"] .toolbar.horizontal li { float: none; } } -@media only screen and (min-width: 16.5em) { - .js .toolbar .bar .tab, - .js .toolbar .horizontal li { +/* This min-width media query is meant to provide basic horizontal layout to + * the main menu tabs when JavaScript is disabled on user agents that understand + * media queries. */ +@media (min-width:16.5em) { + .toolbar .bar .tab, + .toolbar.horizontal li { float: left; /* LTR */ } - .js[dir="rtl"] .toolbar .bar .tab, - .js[dir="rtl"] .toolbar .horizontal li { + [dir="rtl"] .toolbar .bar .tab, + [dir="rtl"] .toolbar.horizontal li { float: right; } } -@media only screen and (min-width: 28.125em) { - .js .toolbar .bar { - position: fixed; - } +/* Present the admin toolbar tabs horizontally when the configured narrow + * breakpoint is active. */ +.toolbar-oriented .bar .tab, +.toolbar-oriented .horizontal li { + float: left; /* LTR */ +} +[dir="rtl"] .toolbar-oriented .bar .tab, +[dir="rtl"] .toolbar-oriented .horizontal li { + float: right; } /** * Toolbar tray. */ -.js .toolbar .tray { - display: none; - position: fixed; -} -/* Make vertical toolbar tray scroll with page for touch devices. */ -.touch .toolbar .tray { - position: absolute; -} .toolbar .tray { - z-index: 1200; -} -.toolbar .horizontal { - width: 100%; + display: none; + z-index: 501; } -.toolbar .vertical, -.toolbar .vertical > .lining:before { - bottom: 0; - width: 240px; - width: 15rem; +.toolar .tray > .lining { + position: relative; } -.toolbar .vertical { +.toolbar-oriented .vertical { left: -100%; /* LTR */ position: absolute; + width: 240px; + width: 15rem; } -[dir="rtl"] .toolbar .vertical { +[dir="rtl"] .toolbar-oriented .vertical { left: auto; right: -100%; } -.toolbar .horizontal { - left: 0; /* LTR */ - height: 0; - /* Set one higher than the contextual links gear. */ - z-index: 1000; -} -[dir="rtl"] .toolbar .horizontal { - left: auto; - right: 0; -} -.toolar .tray .lining { - position: relative; +.toolbar .vertical > .lining { + min-height: 100%; } -.toolbar .vertical > .lining, .toolbar .vertical > .lining:before { - left: -100%; /* LTR */ - min-height: 100%; - overflow-x: hidden; - overflow-y: auto; - position: absolute; width: 100%; } -[dir="rtl"] .toolbar .vertical > .lining, +.toolbar-oriented .vertical > .lining:before { + bottom: 0; + content: ''; + display: block; + left: 0; /* LTR */ + position: fixed; + top: 0; + width: 240px; + width: 15rem; + z-index: -1; +} [dir="rtl"] .toolbar .vertical > .lining:before { left: auto; - right: -100%; + right: 0; } -.toolbar .vertical > .lining:before { - bottom: 0; - -moz-box-sizing: content-box; - -o-box-sizing: content-box; - -webkit-box-sizing: content-box; - box-sizing: content-box; - content: ''; +/* Hide secondary menus when the tray is horizontal. */ +.toolbar-oriented .horizontal .menu li ul { display: none; +} +/* When the configured standard breakpoint is active and the tray is in a + * horizontal position, the tray is fixed to the top of the viewport and does + * not scroll with the page contents. */ +body.toolbar-paneled .toolbar .horizontal { + position: fixed; +} +/* When the configured standard breakpoint is active and the tray is in a + * vertical position, the tray does not scroll with the page. The contents of + * the tray scroll within the confines of the viewport. */ +body.toolbar-paneled .toolbar .vertical { height: 100%; - /* Support for devices that do not support position fixed. */ - position: absolute; + overflow-x: hidden; + overflow-y: auto; position: fixed; - top: 0; - z-index: -1; } .toolbar .tray.active { display: block; } -.toolbar .horizontal.active { - height: auto; -} -.toolbar .vertical.active, -.toolbar .vertical.active > .lining { - bottom: 0; +/* Bring the tray into the viewport. By default it is just off-screen. */ +.toolbar-oriented .vertical.active { left: 0; /* LTR */ - top: 0; } -[dir="rtl"] .toolbar .vertical.active, -[dir="rtl"] .toolbar .vertical.active > .lining { +[dir="rtl"] .toolbar-oriented .vertical.active { left: auto; right: 0; } -/* Make vertical toolbar tray scroll with page for touch devices. */ -.touch .toolbar .vertical.active, -.touch .toolbar .vertical.active > .lining { - bottom: auto; - top: auto; +/* When the configured standard breakpoint is active, the tray appears to push + * the page content away from the edge of the viewport. */ +body.toolbar-vertical.toolbar-paneled { + margin-left: 240px; /* LTR */ + margin-left: 15rem; /* LTR */ } -.toolbar .horizontal .menu li ul { - display: none; -} -@media only screen { - .toolbar .vertical, - .toolbar .vertical > .lining:before { - bottom: auto; - width: 100%; - } +[dir="rtl"] body.toolbar-vertical.toolbar-paneled { + margin-left: auto; + margin-left: auto; + margin-right: 240px; + margin-right: 15rem; } -@media only screen and (min-width: 16.5em) { - .toolbar .vertical { - bottom: 0; - } - .toolbar .vertical, - .toolbar .vertical > .lining:before { - width: 240px; - width: 15rem; - } - .toolbar .vertical.active > .lining:before { - display: block; - left: -1px; /* LTR */ - } - [dir="rtl"] .toolbar .vertical.active > .lining:before { - left: auto; - right: -1px; - } -} -@media only screen and (min-width: 28.125em) { - .toolbar .tray.horizontal { - position: fixed; - } -} -/** - * At larger screen sizes, the tray pushes the page content. - */ -@media only screen and (min-width: 38.125em) { - body.toolbar-tray-open.toolbar-vertical { - margin-left: 240px; /* LTR */ - margin-left: 15rem; /* LTR */ - } - [dir="rtl"] body.toolbar-tray-open.toolbar-vertical { - margin-left: 0; - margin-right: 240px; - margin-right: 15rem; - } -} /** * ToolBar tray orientation toggle. - * - * Hide the orientation toggle from browsers that do not interpret - * media queries. They get a standard horizontal toolbar. */ -.toolbar .horizontal .toggle-orientation { +/* Hide the orientation toggle when the configured narrow breakpoint is not + * active. */ +.toolbar .tray .toggle-orientation { display: none; } -@media only screen { - .toolbar .tray .toggle-orientation { - display: none; - } -} -@media only screen and (min-width: 16.5em) { - .toolbar .tray .toggle-orientation { - display: block; - } +/* Show the orientation toggle when the configured narrow breakpoint is + * active. */ +.toolbar-oriented .tray .toggle-orientation { + display: block; } -.toolbar .horizontal .toggle-orientation { +.toolbar-oriented .horizontal .toggle-orientation { bottom: 0; position: absolute; right: 0; /* LTR */ - top: 0; + top: auto; } -[dir="rtl"] .toolbar .horizontal .toggle-orientation { +[dir="rtl"] .toolbar-oriented .horizontal .toggle-orientation { left: 0; right: auto; } -.toolbar .vertical .toggle-orientation { +.toolbar-oriented .vertical .toggle-orientation { float: right; /* LTR */ width: 100%; } -[dir="rtl"] .toolbar .vertical .toggle-orientation { +[dir="rtl"] .toolbar-oriented .vertical .toggle-orientation { float: left; } diff --git a/core/modules/toolbar/css/toolbar.theme.css b/core/modules/toolbar/css/toolbar.theme.css index 7b08b79..1761198 100644 --- a/core/modules/toolbar/css/toolbar.theme.css +++ b/core/modules/toolbar/css/toolbar.theme.css @@ -63,20 +63,14 @@ padding-right: 0; padding-left: 5em; } -.toolbar .vertical > .lining, .toolbar .vertical > .lining:before { background-color: #ffffff; border-right: 1px solid #aaaaaa; /* LTR */ + box-shadow: -1px 0 5px 2px rgba(0, 0, 0, 0.3333); /* LTR */ } -[dir="rtl"] .toolbar .vertical > .lining, [dir="rtl"] .toolbar .vertical > .lining:before { border-left: 1px solid #aaaaaa; border-right: 0 none; -} -.toolbar .vertical > .lining:before { - box-shadow: -1px 0 5px 2px rgba(0, 0, 0, 0.3333); /* LTR */ -} -[dir="rtl"] .toolbar .vertical > .lining:before { box-shadow: 1px 0 5px 2px rgba(0, 0, 0, 0.3333); } .toolbar .horizontal { diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js index 3e12b55..4dfc1c8 100644 --- a/core/modules/toolbar/js/toolbar.js +++ b/core/modules/toolbar/js/toolbar.js @@ -31,6 +31,7 @@ var $messages; * Holds the mediaQueryList object. */ var mql = { + narrow: null, standard: null, wide: null }; @@ -45,6 +46,11 @@ var mql = { */ Drupal.behaviors.toolbar = { attach: function(context) { + // Verify that the sser agent understands media queries. Complex admin + // toolbar layouts require media query support. + if (!window.matchMedia('only screen').matches) { + return; + }; var options = $.extend(this.options, drupalSettings.toolbar); var $toolbarOnce = $(context).find('#toolbar-administration').once('toolbar'); if ($toolbarOnce.length) { @@ -71,12 +77,17 @@ Drupal.behaviors.toolbar = { // Add the tray orientation toggles. .find('.lining') .append(Drupal.theme('toolbarOrientationToggle')); - // Store media queries. + // Store media queries and attach a handler. + mql.narrow = window.matchMedia(options.breakpoints['module.toolbar.narrow']); + mql.narrow.addListener(Drupal.toolbar.narrowMediaQueryChangeHandler); mql.standard = window.matchMedia(options.breakpoints['module.toolbar.standard']); - // Set up switching between the vertical and horizontal presentation - // of the toolbar trays based on a breakpoint. + mql.standard.addListener(Drupal.toolbar.standardMediaQueryChangeHandler); mql.wide = window.matchMedia(options.breakpoints['module.toolbar.wide']); - mql.wide.addListener(Drupal.toolbar.mediaQueryChangeHandler); + mql.wide.addListener(Drupal.toolbar.wideMediaQueryChangeHandler); + // Fire each MediaQuery change handler so they process once. + Drupal.toolbar.narrowMediaQueryChangeHandler.call(this, mql.narrow); + Drupal.toolbar.standardMediaQueryChangeHandler.call(this, mql.standard); + Drupal.toolbar.wideMediaQueryChangeHandler.call(this, mql.wide); // Set the orientation of the tray. // If the tray is set to vertical in localStorage, persist the vertical // presentation. If the tray is not locked to vertical, let the media @@ -106,6 +117,7 @@ Drupal.behaviors.toolbar = { // Default options. options: { breakpoints: { + 'module.toolbar.narrow': '', 'module.toolbar.standard': '', 'module.toolbar.wide': '' } @@ -176,18 +188,23 @@ Drupal.toolbar.toggleTray = function (event) { * viewport offset distances calculated by Drupal.displace(). */ Drupal.toolbar.adjustPlacement = function (event, offsets) { - // Set the top of the all the trays to the height of the bar. - var barHeight = $toolbar.find('.bar').outerHeight(); - var bhpx = barHeight + 'px'; - var tray; - for (var i = 0, il = $trays.length; i < il; i++) { - tray = $trays[i]; - if (!tray.style.top.length || (tray.style.top !== bhpx)) { - tray.style.top = bhpx; - } + if (!mql.narrow.matches) { + var $body = $('body'); + var $trays = $toolbar.find('.tray'); + // Alter the padding on the top of the body element. + $body.css('padding-top', 0); + $trays.css('padding-top', 0); + // Remove any orientation classes. Make vertical the default for trays. + $body.removeClass('toolbar-vertical toolbar-horizontal'); + $trays.removeClass('horizontal').addClass('vertical'); + } + else { + // Alter the padding on the top of the body element. + $('body').css('padding-top', offsets.top); + // The navbar container is invisible. Its placement is used to determine the + // container for the trays. + $toolbar.find('.tray').css('padding-top', $toolbar.find('.bar').outerHeight()); } - // Alter the padding on the top of the body element. - $('body').css('padding-top', offsets.top); }; /** @@ -199,20 +216,53 @@ Drupal.toolbar.adjustPlacement = function (event, offsets) { Drupal.toolbar.setTrayWidth = function () { var dir = document.documentElement.dir; var edge = (dir === 'rtl') ? 'right' : 'left'; - // Remove the left offset from the trays. + // Remove the side offset from the trays. $toolbar.find('.tray').removeAttr('data-offset-' + edge + ' data-offset-top'); - // If an active vertical tray exists, mark it as an offset element. - $toolbar.find('.tray.vertical.active').attr('data-offset-' + edge, ''); - // If an active horizontal tray exists, mark it as an offset element. - $toolbar.find('.tray.horizontal.active').attr('data-offset-top', ''); + // If the page is wider than the narrow media query, apply offset attributes. + if (mql.narrow.matches) { + // If an active vertical tray exists, mark it as an offset element. + $toolbar.find('.tray.vertical.active').attr('data-offset-' + edge, ''); + // If an active horizontal tray exists, mark it as an offset element. + $toolbar.find('.tray.horizontal.active').attr('data-offset-top', ''); + } // Trigger a recalculation of viewport displacing elements. Drupal.displace(); }; /** - * Respond to configured media query applicability changes. + * Respond to configured narrow media query changes. + */ +Drupal.toolbar.narrowMediaQueryChangeHandler = function (mql) { + var $bar = $toolbar.find('.bar'); + if (mql.matches) { + $bar.attr('data-offset-top', ''); + } + else { + $bar.removeAttr('data-offset-top'); + } + // Toggle between a basic vertical view and a more sophisticated horizontal + // and vertical display of the toolbar bar and trays. + $toolbar.toggleClass('toolbar-oriented', mql.matches); + if (mql.matches) { + changeOrientation('vertical'); + } + // Update the page and toolbar dimension indicators. + updatePeripherals(); +}; + +/** + * Respond to configured standard media query changes. + */ +Drupal.toolbar.standardMediaQueryChangeHandler = function (mql) { + $('body').toggleClass('toolbar-paneled', mql.matches); + // Update the page and toolbar dimension indicators. + updatePeripherals(); +}; + +/** + * Respond to configured wide media query changes. */ -Drupal.toolbar.mediaQueryChangeHandler = function (mql) { +Drupal.toolbar.wideMediaQueryChangeHandler = function (mql) { var orientation = (mql.matches) ? 'horizontal' : 'vertical'; changeOrientation(orientation); // Update the page and toolbar dimension indicators. diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 26520c6..f54d715 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -91,7 +91,6 @@ function toolbar_element_info() { '#attributes' => array( 'id' => 'toolbar-bar', 'class' => array('bar', 'clearfix',), - 'data-offset-top' => array(), ), ), ); diff --git a/core/modules/tour/css/tour.module.css b/core/modules/tour/css/tour.module.css index c96ce49..f8796f3 100644 --- a/core/modules/tour/css/tour.module.css +++ b/core/modules/tour/css/tour.module.css @@ -4,23 +4,23 @@ */ /* Tab appearance. */ -.js .toolbar .bar .tour-toolbar-tab.tab { +.toolbar .bar .tour-toolbar-tab.tab { float: right; /* LTR */ } -.js[dir="rtl"] .toolbar .bar .tour-toolbar-tab.tab { +[dir="rtl"] .toolbar .bar .tour-toolbar-tab.tab { float: left; } -.js .toolbar .tour-toolbar-tab button { +.toolbar .tour-toolbar-tab button { padding-bottom: 1em; padding-top: 1em; color: #fff; font-weight: bold; } -.js .toolbar .tour-toolbar-tab button.active { +.toolbar .tour-toolbar-tab button.active { background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%); background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%); } -.js .tour-toolbar-tab button:focus { +.tour-toolbar-tab button:focus { outline: thin dotted; } @@ -41,6 +41,6 @@ } /* @todo Remove once http://drupal.org/node/1916690 is resolved. */ -.js .toolbar .tour-toolbar-tab.tab.hidden { +.toolbar .tour-toolbar-tab.tab.hidden { display: none; } -- 1.7.10.4