diff --git a/core/modules/responsive_preview/css/responsive-preview.base-rtl.css b/core/modules/responsive_preview/css/responsive-preview.base-rtl.css index 7a314cd..790cc0a 100644 --- a/core/modules/responsive_preview/css/responsive-preview.base-rtl.css +++ b/core/modules/responsive_preview/css/responsive-preview.base-rtl.css @@ -9,16 +9,10 @@ /* At narrow screen widths, float the tab to the right so it falls in line with * the rest of the toolbar tabs. */ -.js .toolbar .bar .responsive-preview-toolbar-tab.tab { - float: right; +.js .toolbar .bar .toolbar-tab-responsive-preview.tab { + float: left; } -/* At wide widths, float the tab to the left. */ -@media only screen and (min-width: 36em) { - .js .toolbar .bar .responsive-preview-toolbar-tab.tab { - float: left; - } -} -.responsive-preview-toolbar-tab .responsive-preview-options { +.toolbar-tab-responsive-preview .responsive-preview-options { left: 0.3em; right: auto; } diff --git a/core/modules/responsive_preview/css/responsive-preview.base.css b/core/modules/responsive_preview/css/responsive-preview.base.css index b98ef78..cd82f1b 100644 --- a/core/modules/responsive_preview/css/responsive-preview.base.css +++ b/core/modules/responsive_preview/css/responsive-preview.base.css @@ -14,36 +14,30 @@ /** * Toolbar tab. */ -.responsive-preview-toolbar-tab { +.toolbar-tab-responsive-preview { display: none; } /* At narrow screen widths, float the tab to the left so it falls in line with * the rest of the toolbar tabs. */ -.js .toolbar .bar .responsive-preview-toolbar-tab.tab { +.js .toolbar .bar .toolbar-tab-responsive-preview.tab { display: block; - float: left; /* LTR */ + float: right; /* LTR */ position: relative; } -/* At wide widths, float the tab to the right. */ -@media only screen and (min-width: 36em) { - .js .toolbar .bar .responsive-preview-toolbar-tab.tab { - float: right; /* LTR */ - } -} -.responsive-preview-toolbar-tab .trigger { +.toolbar-tab-responsive-preview .trigger { display: block; } /* Device preview options. */ -.responsive-preview-toolbar-tab .item-list { +.toolbar-tab-responsive-preview .item-list { display: none; position: absolute; white-space: nowrap; z-index: 1; } -.responsive-preview-toolbar-tab.open .item-list { +.toolbar-tab-responsive-preview.open .item-list { display: block; } -.js .responsive-preview-toolbar-tab.tab .options li { +.js .toolbar-tab-responsive-preview.tab .options li { float: none; } diff --git a/core/modules/responsive_preview/css/responsive-preview.icons-rtl.css b/core/modules/responsive_preview/css/responsive-preview.icons-rtl.css index 8f94e7b..0c8d2b6 100644 --- a/core/modules/responsive_preview/css/responsive-preview.icons-rtl.css +++ b/core/modules/responsive_preview/css/responsive-preview.icons-rtl.css @@ -3,7 +3,7 @@ * RTL icon styling for responsive preview. */ -.toolbar .bar .responsive-preview-toolbar-tab .icon-responsive-preview:before { +.toolbar .bar .toolbar-tab-responsive-preview .icon-responsive-preview:before { left: auto; /* LTR */ right: 1em; } @@ -12,10 +12,10 @@ * Responsive preview controls icons. */ .responsive-preview .icon-close:before { - left: 8px; + left: 9px; right: auto; } .responsive-preview .icon-orientation:before { left: auto; - right: 8px; + right: 9px; } diff --git a/core/modules/responsive_preview/css/responsive-preview.icons.css b/core/modules/responsive_preview/css/responsive-preview.icons.css index 4cd26a3..e616c2c 100644 --- a/core/modules/responsive_preview/css/responsive-preview.icons.css +++ b/core/modules/responsive_preview/css/responsive-preview.icons.css @@ -2,7 +2,7 @@ * @file * Responsive preview icon styling. */ -.responsive-preview-toolbar-tab .icon:before, +.toolbar-tab-responsive-preview .icon:before, .responsive-preview .icon:before { background-attachment: scroll; background-color: transparent; @@ -13,7 +13,7 @@ position: absolute; z-index: 1; } -.toolbar .bar .responsive-preview-toolbar-tab .icon:before { +.toolbar .bar .toolbar-tab-responsive-preview .icon:before { width: 13px; } .responsive-preview button.icon { @@ -30,19 +30,38 @@ padding-right: 0; width: 5em; } -.responsive-preview-toolbar-tab .icon.icon-responsive-preview:before { +.toolbar-tab-responsive-preview .icon.icon-responsive-preview:before { background-position: center top; } -.responsive-preview-toolbar-tab.open .icon-responsive-preview:before, -.responsive-preview-toolbar-tab .icon-responsive-preview.active:before, -.responsive-preview-toolbar-tab .icon-responsive-preview:hover:before { +.toolbar-tab-responsive-preview.open .icon-responsive-preview:before, +.toolbar-tab-responsive-preview .icon-responsive-preview.active:before, +.toolbar-tab-responsive-preview .icon-responsive-preview:hover:before { background-position: center -22px; } -.toolbar .bar .responsive-preview-toolbar-tab .icon-responsive-preview:before { +.toolbar .bar .toolbar-tab-responsive-preview .icon-responsive-preview:before { left: 1em; /* LTR */ height: 22px; top: 0.6667em; } +.toolbar .toolbar-tab-responsive-preview.tab .options .device.icon-active { + padding-left: 2.25em; +} +.toolbar .toolbar-tab-responsive-preview.tab .options .device.icon-active:before { + background-position: -999px -999px; +} +.toolbar .toolbar-tab-responsive-preview.tab .options .device.icon-active.active:before { + background-position: center -110px; +} +@media only screen and (min-width: 16.5em) { + .toolbar .toolbar-tab-responsive-preview.tab .options .device.icon-active { + padding: 0.5em 1.3333em 0.5em 2.25em; + text-indent: 0; + width: auto; + } + .toolbar .toolbar-tab-responsive-preview.tab .options .device.icon-active:before { + left: 0.667em; + } +} /** * Responsive preview controls icons. @@ -50,11 +69,11 @@ .responsive-preview .control.icon:before { height: 12px; width: 12px; - top: 10px; + top: 12px; } .responsive-preview .icon-close:before { background-position: left -44px; - right: 8px; /* LTR */ + right: 9px; /* LTR */ } .responsive-preview .icon-close:active:before, .responsive-preview .icon-close.active:before, @@ -63,7 +82,7 @@ } .responsive-preview .icon-orientation:before { background-position: left -68px; - left: 8px; /* LTR */ + left: 9px; /* LTR */ } .responsive-preview .icon-orientation:hover:before { background-position: left -80px; diff --git a/core/modules/responsive_preview/css/responsive-preview.theme-rtl.css b/core/modules/responsive_preview/css/responsive-preview.theme-rtl.css index 6cfa4f8..b8892ab 100644 --- a/core/modules/responsive_preview/css/responsive-preview.theme-rtl.css +++ b/core/modules/responsive_preview/css/responsive-preview.theme-rtl.css @@ -8,15 +8,15 @@ */ /* Toolbar tab triangle toggle. */ -.responsive-preview-toolbar-tab .trigger:after { +.toolbar-tab-responsive-preview .trigger:after { left: 1em; right: auto; } -.responsive-preview-toolbar-tab.open:before { +.toolbar-tab-responsive-preview.open:before { left: 0; right: auto; } -.responsive-preview-toolbar-tab.open .trigger:after { +.toolbar-tab-responsive-preview.open .trigger:after { left: 0.7em; right: auto; } diff --git a/core/modules/responsive_preview/css/responsive-preview.theme.css b/core/modules/responsive_preview/css/responsive-preview.theme.css index 1c2adf8..ae19d94 100644 --- a/core/modules/responsive_preview/css/responsive-preview.theme.css +++ b/core/modules/responsive_preview/css/responsive-preview.theme.css @@ -6,37 +6,37 @@ /** * Toolbar tab. */ -.responsive-preview-toolbar-tab .options { +.toolbar-tab-responsive-preview .options { background-color: #0f0f0f; } /* Device preview options. */ -.responsive-preview-toolbar-tab .options { +.toolbar-tab-responsive-preview .options { box-shadow: 0 0.8em 2.5em -0.8em rgba(0, 0, 0, 0.75); } -.responsive-preview-toolbar-tab .options li { +.toolbar-tab-responsive-preview .options li { background-color: white; padding: 0; } -.responsive-preview-toolbar-tab .trigger { +.toolbar-tab-responsive-preview .trigger { cursor: pointer; line-height: 1; height: 3em; } -.responsive-preview-toolbar-tab .trigger:hover { +.toolbar-tab-responsive-preview .trigger:hover { background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.125) 20%, transparent 200%); background-image: linear-gradient(rgba(255, 255, 255, 0.125) 20%, transparent 200%); } -.responsive-preview-toolbar-tab .trigger.active, -.responsive-preview-toolbar-tab .trigger.active:hover { +.toolbar-tab-responsive-preview .trigger.active, +.toolbar-tab-responsive-preview .trigger.active:hover { background-image: -webkit-linear-gradient(top, rgb(78,159,234) 0%, rgb(69,132,221) 100%); background-image: linear-gradient(rgb(78,159,234) 0%,rgb(69,132,221) 100%); } -.responsive-preview-toolbar-tab .trigger, -.responsive-preview-toolbar-tab .options .device { +.toolbar-tab-responsive-preview .trigger, +.toolbar-tab-responsive-preview .options .device { padding-bottom: 1em; padding-top: 1em; } -.responsive-preview-toolbar-tab .options .device { +.toolbar-tab-responsive-preview .options .device { background: none; border: none; cursor: pointer; @@ -44,15 +44,16 @@ font-size: 1em; padding: 0.5em 1.3333em } -.toolbar .responsive-preview-toolbar-tab.tab .options .device { +.toolbar .toolbar-tab-responsive-preview.tab .options .device { color: #777; } -.toolbar .responsive-preview-toolbar-tab.tab .options .device:hover { +.toolbar .toolbar-tab-responsive-preview.tab .options .device:hover, +.toolbar .toolbar-tab-responsive-preview.tab .options .device.active { color: black; } /* Toolbar tab triangle toggle. */ -.responsive-preview-toolbar-tab .trigger:after { +.toolbar-tab-responsive-preview .trigger:after { border-bottom-color: transparent; border-left-color: transparent; border-right-color: transparent; @@ -71,7 +72,7 @@ width: 0; z-index: 1 } -.responsive-preview-toolbar-tab.open:before { +.toolbar-tab-responsive-preview.open:before { background-color: white; bottom: 0; content: ' '; @@ -82,19 +83,19 @@ width: 2em; z-index: 1; } -.responsive-preview-toolbar-tab.open .trigger:after { +.toolbar-tab-responsive-preview.open .trigger:after { border-bottom: 0.4545em solid; border-top-color: transparent; color: black; right: 0.7em; /* LTR */ top: 1.25em; } -.responsive-preview-toolbar-tab:hover .trigger:after, -.responsive-preview-toolbar-tab .trigger.active:after, -.responsive-preview-toolbar-tab:hover .trigger.active:after { +.toolbar-tab-responsive-preview:hover .trigger:after, +.toolbar-tab-responsive-preview .trigger.active:after, +.toolbar-tab-responsive-preview:hover .trigger.active:after { color: white; } -.responsive-preview-toolbar-tab.open:hover .trigger:after { +.toolbar-tab-responsive-preview.open:hover .trigger:after { color: black; } @@ -134,6 +135,23 @@ .responsive-preview .control.orientation { left: 0; /* LTR */ } +.responsive-preview .device-label { + color: #e0e0e0; + font-family: sans-serif; + font-size: 0.75em; + font-weight: normal; + left: 40px; + letter-spacing: 0.25ex; + line-height: 2.6667; + margin: 0; + overflow: hidden; + position: absolute; + right: 40px; + text-overflow: ellipsis; + top: 0; + white-space: nowrap; + width: auto; +} /** * Responsive preview frame. diff --git a/core/modules/responsive_preview/images/responsive-preview-icons.png b/core/modules/responsive_preview/images/responsive-preview-icons.png index 167847d..6eedbbe 100644 --- a/core/modules/responsive_preview/images/responsive-preview-icons.png +++ b/core/modules/responsive_preview/images/responsive-preview-icons.png @@ -1,7 +1,10 @@ PNG  - IHDR v~tEXtSoftwareAdobe ImageReadyqe<@IDATxW͎0vH>+8wO7ʩUO=T\ v ©D@gA ;'qؖh-yƓ϶n{_nKr[V3z7MH 8sBnAʠF0" -σTA}z~3O==LȽS@O/c>c_t:5Bb<m}R+u]G)]R:] +8E4A# +H`wwꄎD(/u"*MA"@m؛[~z(b|f{ofV+H ^z= +#_cccj[[[(LⱺaAcfN&x]㛯1YᴗxyYi-g`zG>9NQfH"rZUU3E{+űXDNs-d 1Y[ ɿҝt +aC N +B,VL巧hHzr:6uMnnnZߡ<w-¤,wvww 6?rJ/0^ǝ8??Ju hF٥6 Dtt*B!PzPX|B`D+`6kEAb;...>O&ߛBn<2Ibķ(D"- 0nB PGjfe|||Ay -}jy"S{GPI CXt`*'ANQ]iAj˩!ga)="'2jHW3cV !?QE <_  bxe\@ button') .toggleClass('active', isActive) - .attr('aria-pressed', isActive); + .attr('aria-pressed', isActive) + // Return to $el. + .end() + .find('.device.active') + .removeClass('active') + // Return to $el. + .end() + .find($deviceLink) + .addClass('active'); // When the preview is active, a class on the body is necessary to impose // styling to aid in the display of the preview element. $('body').toggleClass('responsive-preview-active', isActive); @@ -254,18 +267,21 @@ Drupal.responsivePreview.views.TabView = Backbone.View.extend({ }, /** - * Updates the model to reflect the dimensions of the chosen device. + * Updates the model to reflect the properties of the chosen device. * * @param Object event * A jQuery event object. */ - updateDimensions: function (event) { + selectDevice: function (event) { var $link = $(event.target); // Update the device dimensions. - this.model.set('dimensions', { - 'width': parseInt($link.data('responsive-preview-width'), 10), - 'height': parseInt($link.data('responsive-preview-height'), 10), - 'dppx': parseFloat($link.data('responsive-preview-dppx'), 10) + this.model.set({ + 'activeDevice': $link.get(0), + 'dimensions': { + 'width': parseInt($link.data('responsive-preview-width'), 10), + 'height': parseInt($link.data('responsive-preview-height'), 10), + 'dppx': parseFloat($link.data('responsive-preview-dppx'), 10) + } }); // Toggle the preview on. this.model.set('isActive', true); @@ -297,7 +313,7 @@ Drupal.responsivePreview.views.PreviewView = Backbone.View.extend({ this.model.on('change:isRotated', this.render, this); - this.tabModel.on('change:isActive change:dimensions', this.render, this); + this.tabModel.on('change:isActive change:dimensions change:activeDevice', this.render, this); // Recalculate the size of the preview container when the window resizes. this.envModel.on('change:viewportWidth', this.render, this); @@ -396,6 +412,7 @@ Drupal.responsivePreview.views.PreviewView = Backbone.View.extend({ */ _refresh: function () { var isRotated = this.model.get('isRotated'); + var $deviceLink = $(this.tabModel.get('activeDevice')); var $container = this.$el.find('#responsive-preview-frame-container'); var $frame = $container.find('> iframe'); @@ -441,6 +458,15 @@ Drupal.responsivePreview.views.PreviewView = Backbone.View.extend({ // Scale if not responsive. this._scaleIfNotResponsive(); + + // Update the device label. + $container.find('.device-label').text(Drupal.t('@label (@widthpx by @heightpx, @dpidppx, @orientation)', { + '@label': $deviceLink.text(), + '@width': Math.ceil(width), + '@height': Math.ceil(height), + '@dpi': dimensions.dppx, + '@orientation': (isRotated) ? this.strings.landscape : this.strings.portrait + })); }, /** @@ -627,6 +653,7 @@ $.extend(Drupal.theme, { */ responsivePreviewFrameContainer: function () { return '
' + + '' + '' + '' + '
'; diff --git a/core/modules/responsive_preview/responsive_preview.info b/core/modules/responsive_preview/responsive_preview.info index 1930a4d..e10cfe1 100644 --- a/core/modules/responsive_preview/responsive_preview.info +++ b/core/modules/responsive_preview/responsive_preview.info @@ -3,3 +3,5 @@ description = Provides a component that previews a page in various device dimens package = Core version = VERSION core = 8.x + +dependencies[] = testswarm diff --git a/core/modules/responsive_preview/responsive_preview.module b/core/modules/responsive_preview/responsive_preview.module index 6eb095a..3ee5395 100644 --- a/core/modules/responsive_preview/responsive_preview.module +++ b/core/modules/responsive_preview/responsive_preview.module @@ -34,7 +34,7 @@ function responsive_preview_get_devices_list() { '#tag' => 'button', '#value' => $info['label'], '#attributes' => array( - 'class' => array('device'), + 'class' => array('device', 'icon', 'icon-active'), 'data-responsive-preview-width' => ($info['dimensions']['width']) ? $info['dimensions']['width'] : '', 'data-responsive-preview-height' => ($info['dimensions']['height']) ? $info['dimensions']['height'] : '', 'data-responsive-preview-dppx' => ($info['dimensions']['dppx']) ? $info['dimensions']['dppx'] : '1', @@ -79,8 +79,8 @@ function responsive_preview_toolbar() { ), ), '#wrapper_attributes' => array( - 'id' => 'toolbar-tab-responsive-preview', - 'class' => array('responsive-preview-toolbar-tab'), + 'id' => 'responsive-preview-toolbar-tab', + 'class' => array('toolbar-tab-responsive-preview'), ), '#attached' => array( 'library' => array( @@ -125,3 +125,48 @@ function responsive_preview_library_info() { return $libraries; } + +/** + * Implements hook_testswarm_tests(). + */ +function responsive_preview_testswarm_tests() { + + $path = drupal_get_path('module', 'responsive_preview'); + + return array( + 'responsivePreview' => array( + 'module' => 'responsive_preview', + 'description' => 'Test the responsive preview module.', + 'js' => array( + $path . '/tests/testswarm/responsive_preview.tests.js' => array(), + array( + 'data' => array( + 'responsive_preview' => array( + 'devices' => config('responsive_preview.devices')->get() + ), + ), + 'type' => 'setting', + ), + ), + 'dependencies' => array( + array('system', 'jquery'), + array('system', 'drupalSettings'), + array('testswarm', 'jquery.simulate'), + ), + 'path' => '', + 'permissions' => array() + ), + 'responsivePreviewAdmin' => array( + 'module' => 'responsive_preview', + 'description' => 'Test the responsive preview module admin.', + 'js' => array( + $path . '/tests/testswarm/responsive_preview.admin.tests.js' => array(), + ), + 'dependencies' => array( + array('system', 'jquery'), + ), + 'path' => 'admin', + 'permissions' => array() + ), + ); +} diff --git a/core/modules/responsive_preview/tests/testswarm/responsive_preview.admin.tests.js b/core/modules/responsive_preview/tests/testswarm/responsive_preview.admin.tests.js new file mode 100644 index 0000000..b0466e9 --- /dev/null +++ b/core/modules/responsive_preview/tests/testswarm/responsive_preview.admin.tests.js @@ -0,0 +1,27 @@ +/*jshint strict:true, browser:true, curly:true, eqeqeq:true, expr:true, forin:true, latedef:true, newcap:true, noarg:true, trailing: true, undef:true, unused:true */ +/*global Drupal: true, jQuery: true, QUnit:true*/ +(function ($, Drupal, drupalSettings, window, document, undefined) { + "use strict"; + Drupal.tests.responsivePreviewAdmin = { + getInfo: function() { + return { + name: 'Responsive Preview', + description: 'Tests for the responsive preview admin.', + group: 'Core' + }; + }, + setup: function () {}, + teardown: function () {}, + tests: { + toolbarTab: function ($, Drupal, window, document, undefined) { + return function() { + QUnit.expect(1); + + // The toolbar tab should not be present on an admin path. + var $tab = $('.toolbar .toolbar-tab-responsive-preview'); + QUnit.equal($tab.length, 0, Drupal.t('The tab is not present.')); + }; + } + } + }; +})(jQuery, Drupal, drupalSettings, this, this.document); diff --git a/core/modules/responsive_preview/tests/testswarm/responsive_preview.tests.js b/core/modules/responsive_preview/tests/testswarm/responsive_preview.tests.js new file mode 100644 index 0000000..f3f66cc --- /dev/null +++ b/core/modules/responsive_preview/tests/testswarm/responsive_preview.tests.js @@ -0,0 +1,69 @@ +/*jshint strict:true, browser:true, curly:true, eqeqeq:true, expr:true, forin:true, latedef:true, newcap:true, noarg:true, trailing: true, undef:true, unused:true */ +/*global Drupal: true, jQuery: true, QUnit:true*/ +(function ($, Drupal, drupalSettings, window, document, undefined) { + "use strict"; + Drupal.tests.responsivePreview = { + getInfo: function() { + return { + name: 'Responsive Preview', + description: 'Tests for the responsive preview feature.', + group: 'Core' + }; + }, + setup: function () {}, + teardown: function () { + // Close the preview container. + $('#responsive-preview-close').trigger('click'); + }, + tests: { + toolbarTab: function ($, Drupal, window, document, undefined) { + return function() { + QUnit.expect(3); + + // Find the toolbar tab. + var $tab = $('.toolbar .toolbar-tab-responsive-preview'); + QUnit.equal($tab.length, 1, Drupal.t('The tab is present.')); + + // Verify the tab dropdown click functionality. + $tab.find('> .trigger').trigger('click'); + QUnit.ok($tab.hasClass('open'), Drupal.t('The tab dropdown list opens.')); + + // Verify the number of devices in the list. + var devices = drupalSettings.responsive_preview.devices; + var count = 0; + for (var device in devices) { + if (devices.hasOwnProperty(device)) { + count++; + } + } + var $devices = $tab.find('.options .device'); + QUnit.equal($devices.length, count, Drupal.t('The correct number of devices are listed.')); + }; + }, + previewLaunch: function ($, Drupal, window, document, undefined) { + return function () { + QUnit.expect(3); + + // Find the toolbar tab. + var $tab = $('.toolbar .toolbar-tab-responsive-preview'); + // Verify that the responsive preview container is not been built yet. + var $container = $('#responsive-preview'); + QUnit.equal($container.length, 0, Drupal.t('The preview container does not exist yet.')); + + // Verify that clicking a device link activates the preview container. + $tab.find('.options .device').first().trigger('click'); + QUnit.stop(); + window.setTimeout(function () { + $container = $('#responsive-preview'); + // Verify that the preview container exists. + QUnit.equal($container.length, 1, Drupal.t('The preview container exists.')); + + // Verify that preview container is active. + QUnit.ok($container.hasClass('active'), Drupal.t('The preview container is active.')); + QUnit.start(); + }, 500); + }; + } + } + }; +})(jQuery, Drupal, drupalSettings, this, this.document);