Index: branches/RC/core/units/categories/categories_tag_processor.php =================================================================== diff -u -N -r11931 -r11963 --- branches/RC/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 11931) +++ branches/RC/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 11963) @@ -1,6 +1,6 @@ '#BLOCK#', 'theme-file_event' => '#EVENT#', 'theme_id' => $theme_id, 'source' => $template, 'pass' => 'all,theme-file', 'front' => 1, 'no_amp' => 1); $edit_template_url = $this->Application->HREF('themes/template_edit', ADMIN_DIRECTORY, $url_params, 'index.php'); + + $url_params = Array ('theme-file_event' => 'OnSaveLayout', 'source' => $template, 'pass' => 'all,theme-file', 'no_amp' => 1); + $save_layout_url = $this->Application->HREF('index', '', $url_params); + $this_url = $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', 'no_amp' => 1)); - $ret .= "var aTemplateManager = new TemplateManager('" . $edit_template_url . "', '" . $this_url . "', " . (int)EDITING_MODE . ");\n"; + $ret .= "var aTemplateManager = new TemplateManager('" . $edit_template_url . "', '" . $this_url . "', '" . $save_layout_url . "', " . (int)EDITING_MODE . ");\n"; $ret .= "var \$modal_windows = " . ($this->Application->ConfigValue('UseModalWindows') ? 'true' : 'false') . ";\n"; $ret .= "var main_title = '" . addslashes( $this->Application->ConfigValue('Site_Name') ) . "';" . "\n"; @@ -1427,7 +1431,19 @@ $edit_url = $this->Application->HREF('categories/categories_edit', '/admin', $url_params); - $edit_btn = ' + $edit_btn = ''; + + if (EDITING_MODE == EDITING_MODE_LAYOUT) { + $edit_btn .= ' +
+
+ +
+
Save Layout
+
' . "\n"; + } + + $edit_btn .= '
Index: branches/RC/core/admin_templates/incs/cms.css =================================================================== diff -u -N -r11690 -r11963 --- branches/RC/core/admin_templates/incs/cms.css (.../cms.css) (revision 11690) +++ branches/RC/core/admin_templates/incs/cms.css (.../cms.css) (revision 11963) @@ -16,7 +16,7 @@ padding: 5px; } -div.cms-section-properties-btn, div.cms-edit-btn { +div.cms-section-properties-btn, div.cms-edit-btn, div.cms-save-layout-btn { padding: 2px 5px; font-family: Arial, Verdana; font-size: 13px; @@ -55,8 +55,19 @@ margin-left: -10px; border: 2px solid #FF6E00; background-color: #FFCC00; + opacity: 0.5; } +/* === Styles for "Save Layout" button === */ +div.cms-save-layout-btn { + float: left; + position: absolute; + + margin-left: -10px; + border: 2px solid #A1D0A1; + background-color: #CCFF00; +} + /* === Styles for Template Editor === */ div.block-edit-btn-container { border: 1px dashed transparent; Index: branches/RC/themes/default2009/index.tpl =================================================================== diff -u -N -r11670 -r11963 --- branches/RC/themes/default2009/index.tpl (.../index.tpl) (revision 11670) +++ branches/RC/themes/default2009/index.tpl (.../index.tpl) (revision 11963) @@ -4,50 +4,52 @@
##--> - + -
- +
+
+ +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
- -
-
- -
+
+
+ +
+
+ + + + -
- - - - - - - + + +
+
+ + + +
- -
- - - -
Index: branches/RC/core/units/general/helpers/template_helper.php =================================================================== diff -u -N -r11892 -r11963 --- branches/RC/core/units/general/helpers/template_helper.php (.../template_helper.php) (revision 11892) +++ branches/RC/core/units/general/helpers/template_helper.php (.../template_helper.php) (revision 11963) @@ -1,6 +1,6 @@ Application->InitParser(); // we have no parser when saving block content + + $this->_getSourceTemplate(); + + $filename = $this->Application->TemplatesCache->GetRealFilename($this->_sourceTemplate) . '.tpl'; + if (!is_writable($filename)) { + // we can't save changes, don't bother calculating new template contents + return false; + } + + $data = file_get_contents($filename); + + $line_ending = strpos($data, "\r") !== false ? "\r\n" : "\n"; + + // 1. get location of movable areas + $mask = ''; + $start_pos = 0; + $elements = Array (); + $areas = $this->_getDivPairs($data, 'movable-area'); + foreach ($areas as $area_index => $area) { + // 1.1. get locations of all movable elements inside given area + $area_content = substr($area['data'], $area['open_len'], -$area['close_len']); + $elements = array_merge($elements, $this->_getDivPairs($area_content, 'movable-element', $area_index, $area['open_pos'] + $area['open_len'])); + + // 1.2. prepare mask to place movable elements into (don't include movable area div ifself) + $mask .= "\t" . substr($data, $start_pos, $area['open_pos'] + $area['open_len'] - $start_pos) . $line_ending . "\t\t" . '#AREA' . $area_index . '#' . $line_ending; + $start_pos = $area['close_pos'] - $area['close_len']; + } + $mask = trim($mask . "\t" . substr($data, $area['close_pos'] - $area['close_len'])); + + if (!$elements) { + // no elements found + return false; + } + + foreach ($areas as $area_index => $area) { + $area_content = ''; + $target_elements = $target_order[$area_index]; + foreach ($target_order[$area_index] as $old_location) { + $area_content .= $elements[$old_location]['data'] . $line_ending . "\t\t"; + } + + $mask = str_replace('#AREA' . $area_index . '#', trim($area_content), $mask); + } + + $fp = fopen($filename, 'w'); + fwrite($fp, $mask); + fclose($fp); + + return true; + } + + /** + * Extracts div pairs with given class from given text + * + * @param string $data + * @param string $class + * @param int $area + * @param int $offset + * @return Array + */ + function _getDivPairs(&$data, $class, $area = null, $offset = 0) + { + preg_match_all('/(]*>)|(<\/div>)/s', $data, $divs, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); + + $skip_count = 0; + $pairs = Array (); + + foreach ($divs as $div) { + if (strpos($div[0][0], '/') === false) { + // opening div + if (strpos($div[0][0], $class) !== false) { + $pair = Array ('open_pos' => $div[0][1], 'open_len' => strlen($div[0][0])); + $skip_count = 0; + } + else { + $skip_count++; + } + } + else { + // closing div + if ($skip_count == 0) { + $pair['close_len'] = strlen($div[0][0]); + $pair['close_pos'] = $div[0][1] + $pair['close_len']; + $pair['data'] = substr($data, $pair['open_pos'], $pair['close_pos'] - $pair['open_pos']); + + if (isset($area)) { + $pair['open_pos'] += $offset; + $pair['close_pos'] += $offset; + // index indicates area + $pairs['a' . $area . 'e' . count($pairs)] = $pair; + } + else { + $pairs[] = $pair; + } + } + else { + $skip_count--; + } + } + } + + return $pairs; + } + + /** * Returns information about parser element locations in template * * @param Array $params Index: branches/RC/themes/default2009/platform/designs/default_design.des.tpl =================================================================== diff -u -N -r11690 -r11963 --- branches/RC/themes/default2009/platform/designs/default_design.des.tpl (.../default_design.des.tpl) (revision 11690) +++ branches/RC/themes/default2009/platform/designs/default_design.des.tpl (.../default_design.des.tpl) (revision 11963) @@ -43,18 +43,18 @@ -
- + +
- +
+
- -
+ @@ -66,8 +66,8 @@ -
- + +
@@ -81,10 +81,10 @@
-
+
+ - -
+
Index: branches/RC/core/units/theme_files/theme_file_eh.php =================================================================== diff -u -N -r11892 -r11963 --- branches/RC/core/units/theme_files/theme_file_eh.php (.../theme_file_eh.php) (revision 11892) +++ branches/RC/core/units/theme_files/theme_file_eh.php (.../theme_file_eh.php) (revision 11963) @@ -1,6 +1,6 @@ Array ('subitem' => true), 'OnSaveBlock' => Array ('subitem' => true), + 'OnSaveLayout' => Array ('subitem' => true), ); $this->permMapping = array_merge($this->permMapping, $permissions); @@ -191,4 +192,29 @@ $event->status = erFAIL; } } + + /** + * Saves layout on given template + * + * @param kEvent $event + */ + function OnSaveLayout(&$event) + { + $event->status = erSTOP; + if (($this->Application->GetVar('ajax') != 'yes') || (EDITING_MODE != EDITING_MODE_LAYOUT)) { + return ; + } + + $target_order = $this->Application->GetVar('target_order'); + + $template_helper =& $this->Application->recallObject('TemplateHelper'); + /* @var $template_helper TemplateHelper */ + + if ($template_helper->moveTemplateElements($target_order)) { + echo 'OK'; + return ; + } + + echo 'FAILED'; + } } \ No newline at end of file Index: branches/RC/core/admin_templates/js/template_manager.js =================================================================== diff -u -N -r11705 -r11963 --- branches/RC/core/admin_templates/js/template_manager.js (.../template_manager.js) (revision 11705) +++ branches/RC/core/admin_templates/js/template_manager.js (.../template_manager.js) (revision 11963) @@ -1,6 +1,7 @@ -function TemplateManager ($edit_url, $browse_url, $edting_mode) { +function TemplateManager ($edit_url, $browse_url, $save_layout_url, $edting_mode) { this._editUrl = $edit_url; this.browseUrl = $browse_url; + this._saveLayoutUrl = $save_layout_url; this.editingMode = $edting_mode; // from 1 to 4 this._blocks = {}; @@ -39,6 +40,9 @@ if ($template_manager.editingMode == 2) { // Layout Mode + + $template_manager.renumberMovableElements(); + $('div.movable-area').sortable( { placeholder: 'move-helper', @@ -51,10 +55,71 @@ } ); } + + $('div.cms-edit-btn') + .mouseover( + function(e) { + $(this).css('opacity', 1); + } + ) + .mouseout( + function(e) { + $(this).css('opacity', 0.5); + } + ); } ); } +TemplateManager.prototype.renumberMovableElements = function () { + var $area_index = 0; + // 1. dynamically assign IDs to all movable elements + $('div.movable-area').each( + function() { + var $element_index = 0; + $('div.movable-element', this).each( + function() { + $(this).attr('id', 'target_order_a' + $area_index + 'e' + $element_index); + $element_index++; + } + ); + + $area_index++; + } + ); +} + +TemplateManager.prototype.saveLayout = function () { + // prepare order string + var $sort_order = []; + $('div.movable-area').each( + function($area_index) { + var $order = $(this).sortable('serialize').replace(/target_order\[\]/g, 'target_order[' + $area_index + '][]'); + if ($order) { + $sort_order.push($order); + } + } + ); + $sort_order = $sort_order.join('&'); + + // save order string + var $me = this; + var $url = this._saveLayoutUrl + '&' + $sort_order; + $.get( + $url, + function(data) { + // only, when data was saved renumber movable elements + if (data == 'OK') { + alert('New Layout Saved'); + $me.renumberMovableElements(); + } + else { + alert('Failed to Save New Layout'); + } + } + ); +} + TemplateManager.prototype.onBtnClick = function ($e, $element) { var $id = $element.id.replace(/_btn$/, ''); var $block_info = this._blocks[$id]; Index: branches/RC/core/admin_templates/tree.tpl =================================================================== diff -u -N -r11749 -r11963 --- branches/RC/core/admin_templates/tree.tpl (.../tree.tpl) (revision 11749) +++ branches/RC/core/admin_templates/tree.tpl (.../tree.tpl) (revision 11963) @@ -12,7 +12,12 @@ } function onTreeFrameResize() { - var $width = $('#sub_frameset', window.parent.document).attr('cols').split(',')[0]; + var $frameset = $('#sub_frameset', window.parent.document); + if (!$frameset.length) { + return ; + } + + var $width = $frameset.attr('cols').split(',')[0]; if (($width <= 0) || ($width == $last_width)) { // don't save zero width return ;