diff --git a/core/modules/display/display.module b/core/modules/display/display.module index 5362711..549a2e5 100644 --- a/core/modules/display/display.module +++ b/core/modules/display/display.module @@ -20,7 +20,7 @@ function display_menu() { 'file' => 'display.admin.inc', ); $items['admin/structure/layouts/manage/%display'] = array( - 'title' => 'View layout', + 'title' => 'Edit layout', 'page callback' => 'display_page_edit', 'page arguments' => array(4), 'access callback' => 'user_access', @@ -81,3 +81,10 @@ function display_entity_info_alter(&$entity_info) { $entity_info['display']['list_path'] = 'admin/structure/layouts'; $entity_info['display']['entity_keys']['label'] = 'label'; } + +/** + * Ajax callback for block placement display switching. + */ +function display_ajax_block_placement_callback($form, &$form_state) { + return $form['blocks']; +} diff --git a/core/modules/display/lib/Drupal/display/DisplayFormController.php b/core/modules/display/lib/Drupal/display/DisplayFormController.php index 2fe67f4..ef5e056 100644 --- a/core/modules/display/lib/Drupal/display/DisplayFormController.php +++ b/core/modules/display/lib/Drupal/display/DisplayFormController.php @@ -20,23 +20,75 @@ class DisplayFormController extends EntityFormController { * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $display) { - // Get list of layouts and expose that for display layout selection. + // Get list of layouts to be exposed for display layout selection. $layouts = drupal_container()->get('plugin.manager.layout')->getDefinitions(); $layout_options = array(); foreach ($layouts as $key => $layout) { $layout_options[$key] = $layout['title']; } + $layout_keys = array_keys($layout_options); + + // Add default values to form_state['values']. + if (!isset($form_state['values'])) { + $form_state['values'] = array(); + } + $form_state['values'] += array( + 'layout' => isset($display->layout) ? $display->layout : reset($layout_keys), + ); + $form['layout'] = array( '#type' => 'select', '#title' => t('Layout'), - '#default_value' => isset($display->layout) ? $display->layout : '', + '#default_value' => $form_state['values']['layout'], '#options' => $layout_options, + '#ajax' => array( + 'callback' => 'display_ajax_block_placement_callback', + 'wrapper' => 'display-blocks', + 'method' => 'replace', + 'effect' => 'fade', + ), + ); + + // To support the Ajax interaction, remap the display to the newly selected + // layout. This will reorganize the blocks as appropriate. + $layout = layout_manager()->createInstance($form_state['values']['layout'], array()); + $display->remapToLayout($layout); + + // Add block editing interface wrapper for Ajax operation. + $form['blocks'] = array( + '#prefix' => '
', + '#suffix' => '
', + 'demonstration' => $this->layoutDemonstration($display), ); return parent::form($form, $form_state, $display); } /** + * Produces a render array demonstration form of the display. + */ + private function layoutDemonstration(EntityInterface $display) { + + // Render the layout in an admin context with region demonstrations. + $layout = layout_manager()->createInstance($display->layout, array()); + $regions = $layout->getRegions(); + foreach ($regions as $region => $info) { + $region_text = '
' . check_plain($info['label']) . '
'; + $region_text .= '
'; + $region_text .= '
'; + $regions[$region] = $region_text; + } + $build['demonstration'] = array( + '#type' => 'markup', + '#markup' => $layout->renderLayout(TRUE, $regions), + ); + $build['#attached']['css'][] = drupal_get_path('module', 'display') . '/display.admin.css'; + $build['#attached']['js'][] = drupal_get_path('module', 'display') . '/display.admin.js'; + $build['#attached']['library'][] = array('system', 'jquery.ui.sortable'); + return $build; + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::actions(). */ protected function actions(array $form, array &$form_state) { diff --git a/core/modules/display/display.admin.css b/core/modules/display/display.admin.css new file mode 100644 index 0000000..3fb706d --- /dev/null +++ b/core/modules/display/display.admin.css @@ -0,0 +1,305 @@ +z#display-blocks { + background-color:#fff; + -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); +} + +z#display-blocks .layout-display { + border: 1px solid #ddd; + padding: 27px; +} + +/** + * Begions. + */ + +#display-blocks .layout-region .region-wrapper { + clear:both; + margin-top: 5px; + padding: 5px 15px 15px 15px; + background-color:rgb(255,255,255); + border-color:rgb(204,204,204); + border-width:1px; + border-style:solid; + -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); +} + +#display-blocks .region_information { + clear:both; + display: block; + width: 100%; + text-align:right; + padding-bottom: 3px; + margin:0; + overflow: hidden; +} + +#display-blocks .region_label { + font-size:11px; + text-transform: uppercase; + letter-spacing:.1em; + margin-right: -.1em; + color: #666; +} + +#display-blocks .region_table { + clear:both; + display: table; + width: 100%; + table-layout:fixed; +} + +/** + * Blocks. + */ + +#display-blocks .region_blocks { + display: table-row; +} + +#display-blocks .block { + clear:both; + display: table-cell; + padding-right:15px; + height: 60px; + overflow: hidden; +} + +#display-blocks .master_block { + position: relative; + display: inline-block; + width: 100%; + height:100%; + background-image:-moz-linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%); + background-image:-webkit-gradient(linear,color-stop(0, rgb(102,149,168)),color-stop(0.99, rgb(92,133,150)),color-stop(1, rgb(92,133,150))); + background-image:-webkit-linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%); + background-image:linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%); +} + +z#display-blocks .layout_block { + position: relative; + display: inline-block; + width: 100%; + height:100%; + background-image:-moz-linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%); + background-image:-webkit-gradient(linear,color-stop(0, rgb(123,194,170)),color-stop(0.99, rgb(114,179,156)),color-stop(1, rgb(114,179,156))); + background-image:-webkit-linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%); + background-image:linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%); +} + +z#display-blocks .page_block { + position: relative; + display: inline-block; + width: 100%; + height:100%; + background-image:-moz-linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%); + background-image:-webkit-gradient(linear,color-stop(0, rgb(137,211,124)),color-stop(0.99, rgb(128,198,117)),color-stop(1, rgb(128,198,117))); + background-image:-webkit-linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%); + background-image:linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%); +} + +#display-blocks .add_block { + display: table-cell; + border: 1px solid #ddd; + width: 60px !important; + height: 60px; + background-image:-moz-linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%); + background-image:-webkit-gradient(linear,color-stop(0, rgb(254,254,254)),color-stop(1, rgb(225,225,225))); + background-image:-webkit-linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%); + background-image:linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%); +} + +#display-blocks .add_block:hover { + border: 1px solid #ccc; + -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); + box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1); +} + +#display-blocks .add_block_press { + border: 1px solid #c5c5c5; + background-image:-moz-linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%); + background-image:-webkit-gradient(linear,color-stop(0, rgb(245,245,245)),color-stop(1, rgb(221,221,221))); + background-image:-webkit-linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%); + background-image:linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%); +} + +#display-blocks .plus_icon { + display: inline-block; + width: 100%; + height: 100%; + background-image:url(plus.png); + background-position:center; + background-repeat:no-repeat; +} + +z#display-blocks .rowspan { + width: 100%; + position: relative; +} + +z#display-blocks .column-left { + position:relative; + float: left; + width: 69.7%; + margin-bottom: 5px; +} + +z#display-blocks .column-right { + float: right; + width: 30%; + margin-bottom: 5px; +} + +/** + * Block information. + */ + +#display-blocks .block_information { + position: relative; + float: left; +} + +#display-blocks .block_type_indicator { + position: absolute; + left:0; + top:0; + width: 22px; + height: 22px; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + text-align: center; + vertical-align:middle; + line-height: 200%; + font-size:11px; + font-weight:bold; +} + +#display-blocks .block_label { + position: absolute; + left: 27px; + top:2px; + font-size:14px; + font-weight:bold; + color:rgb(255,255,255); + text-align:left; + margin-left:3px; +} + +z#display-blocks .pb_text { + color: #555; +} + +z#display-blocks .lb_text { + color: #555; +} + +#display-blocks .mb_text { + color: #fff; +} + +/** + * Block operations. + */ + +#display-blocks .mb_block_operations { + position: absolute; + opacity:0; + left: 0; + top: 23px; + width: 100%; + height: 100%; + text-align: center; + background-color: transparent; + -webkit-transition: all 0.3s; + -webkit-transition-property: all; + -webkit-transition-duration: 0.3s; + -webkit-transition-delay: initial; +} + +#display-blocks .mb_block_operations:hover { + opacity:1; +} + +z#display-blocks .lb_block_operations { + position: absolute; + opacity:0; + left: 0; + top: 23px; + width: 100%; + height: 100%; + text-align: center; + background-color: transparent; + -webkit-transition: all 0.3s; + -webkit-transition-property: all; + -webkit-transition-duration: 0.3s; + -webkit-transition-delay: initial; +} + +z#display-blocks .lb_block_operations:hover { + opacity:1; +} + +z#display-blocks .pb_block_operations { + position: absolute; + opacity:0; + left: 0; + top: 23px; + width: 100%; + height: 100%; + text-align: center; + background-color: transparent; + -webkit-transition: all 0.3s; + -webkit-transition-property: all; + -webkit-transition-duration: 0.3s; + -webkit-transition-delay: initial; +} + +z#display-blocks .pb_block_operations:hover { + opacity:1; +} + +z#display-blocks .drag { + display:inline-block; + width: 25px; + height: 20px; + background-position:center; + background-repeat:no-repeat; +} + +#display-blocks .gear { + display:inline-block; + width:25px; + height:20px; + background-position:center; + background-repeat:no-repeat; +} + +#display-blocks .mb_gear { + background-image:url(gear_fff.png); +} + +z#display-blocks .mb_drag { + background-image:url(drag_fff.png); +} + +z#display-blocks .pb_gear { + background-image:url(gear_555.png); +} + +z#display-blocks .pb_drag { + background-image:url(drag_555.png); +} + +z#display-blocks .lb_gear { + background-image:url(gear_555.png); +} + +z#display-blocks .lb_drag { + background-image:url(drag_555.png); +} + + diff --git a/core/modules/display/display.admin.js b/core/modules/display/display.admin.js new file mode 100644 index 0000000..8298e6c --- /dev/null +++ b/core/modules/display/display.admin.js @@ -0,0 +1,32 @@ +(function ($, window) { + +"use strict"; + +/** + * Add new blocks to a display. + */ +Drupal.behaviors.displayAddBlock = { + attach: function () { + $('.region_table .add_block').click(function () { + var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; + var randomString = ''; + for (var i=0; i < 8; i++) { + var rnum = Math.floor(Math.random() * chars.length); + randomString += chars.substring(rnum,rnum+1); + } + + var block = '
M' + randomString + ' block
'; + $(this).parent().prepend(block); + }); + + // Apply drag and drop behavior. + $('.region_blocks').sortable({ + items: '.block', + connectWith: '.connectedSortable', + cursor: 'move', + }); + $('.region_blocks').disableSelection(); + } +}; + +})(jQuery, window); diff --git a/core/modules/display/gear_fff.png b/core/modules/display/gear_fff.png new file mode 100644 index 0000000..dfd4aae diff --git a/core/modules/display/plus.png b/core/modules/display/plus.png new file mode 100644 index 0000000..b5544c1