From 4cd85f45b5289c7324d957f6f0c5783a4fed7254 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Wed, 18 Jan 2012 11:18:26 +0100 Subject: [PATCH 01/21] overhauled the whole JS and thus added it as v2 --- .../multicolumnwizard/MultiColumnWizard.php | 35 +- .../html/js/multicolumnwizard_src_v2.js | 356 ++++++++++++++++++ 2 files changed, 375 insertions(+), 16 deletions(-) create mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index 1e14f3c..c3ab9d7 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -292,7 +292,7 @@ public function generate() $this->columnFields = $this->{$this->arrCallback[0]}->{$this->arrCallback[1]}($this); } - $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard.js'; + $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js'; $GLOBALS['TL_CSS'][] = 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; $strCommand = 'cmd_' . $this->strField; @@ -367,7 +367,7 @@ public function generate() // Add label and return wizard $return = ' -style) ? ('style="' . $this->style . '"') : ('')) . 'rel="maxCount[' . ($this->maxCount ? $this->maxCount : '0') . '] minCount[' . ($this->minCount ? $this->minCount : '0') . '] unique[' . implode(',', $arrUnique) . '] datepicker[' . implode(',', $arrDatepicker) . ']" cellpadding="0" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard" summary="MultiColumnWizard">'; +
style) ? ('style="' . $this->style . '"') : ('')) . ' cellpadding="0" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard" summary="MultiColumnWizard">'; if ($this->columnTemplate == '') { @@ -547,7 +547,7 @@ public function generate() - $return .= ''; } - return $return . '
buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; // Add buttons foreach ($this->arrButtons as $button => $image) @@ -558,24 +558,24 @@ public function generate() continue; } - $return .= 'maxCount <= $intNumberOfRows && $this->maxCount > 0) - { - $return .= 'style="display:none" '; - } - if ($button == "delete" && $this->minCount >= $intNumberOfRows && $this->minCount > 0) - { - $return .= 'style="display:none" '; - } - - $return .= 'href="' . $this->addToUrl('&' . $strCommand . '=' . $button . '&cid=' . $i . '&id=' . $this->currentRecord) . '" class="widgetImage" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button]) . '" onclick="MultiColumnWizard.execute(this, \'' . $button . '\', \'ctrl_' . $this->strId . '\'); return false;">' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; } $return .= '
'; + $return .= ''; + + $return .= ''; + + return $return; } /** @@ -676,6 +676,9 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) $arrField['eval']['tl_class'] = trim($arrField['eval']['tl_class'] . ' hidelabel'); } + // add class to enable easy updating of "name" attributes etc. + $arrField['eval']['tl_class'] = trim($arrField['eval']['tl_class'] . ' mcwUpdateFields'); + // load callback if (is_array($arrField['load_callback'])) { diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js new file mode 100644 index 0000000..29b28bb --- /dev/null +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js @@ -0,0 +1,356 @@ +/** + * Contao Open Source CMS + * Copyright (C) 2005-2011 Leo Feyer + * + * Formerly known as TYPOlight Open Source CMS. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, please visit the Free + * Software Foundation website at . + * + * PHP version 5 + * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 + * @package MultiColumnWizard + * @license http://opensource.org/licenses/lgpl-3.0.html + */ + +var MultiColumnWizard = new Class( +{ + Implements: [Options], + options: + { + table: null, + maxCount: 0, + minCount: 0, + uniqueFields: [] + }, + + // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) + operationLoadCallbacks: [], + operationClickCallbacks: [], + + /** + * Initialize the wizard + * @param Object options + */ + initialize: function(options) + { + this.setOptions(options); + + // make sure we really have the table as element + this.options.table = document.id(this.options.table); + + // Do not run this in the frontend, Backend class would not be available + if (window.Backend) + { + Backend.getScrollOffset(); + } + + this.updateOperations(); + }, + + + /** + * Update operations + */ + updateOperations: function() + { + var self = this; + + // execute load callback and register click event callback + this.options.table.getElement('tbody').getElements('tr').each(function(el, index) + { + el.getElement('td.operations').getElements('a').each(function(operation) + { + var key = operation.get('rel'); + + // register static load callbacks + if (MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // register instance load callbacks + if (self.operationLoadCallbacks[key]) + { + self.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // remove all click events + operation.removeEvents('click'); + + // register static click callbacks + if (MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); }); + }); + } + + // register instance click callbacks + if (self.operationClickCallbacks[key]) + { + self.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + self.updateFields(index); + }); + }); + } + }); + }); + }, + + + /** + * Update fields + * @param int level + */ + updateFields: function(level) + { + // this in this context refers to the row element + this.getElements('.mcwUpdateFields *[name]').each(function(el) + { + // rewrite elements name + if (typeOf(el.getProperty('name')) == 'string') + { + var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); + if (erg) + { + el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); + } + } + + // rewrite elements id + if (typeOf(el.getProperty('id')) == 'string') + { + var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); + } + } + + // rewrite elements for + if (typeOf(el.getProperty('for')) == 'string') + { + var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); + } + } + }); + }, + + + /** + * Add a load callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!this.operationLoadCallbacks[key]) + { + this.operationLoadCallbacks[key] = []; + } + + this.operationLoadCallbacks[key].push(func); + }, + + + /** + * Add a click callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!this.operationClickCallbacks[key]) + { + this.operationClickCallbacks[key] = []; + } + + this.operationClickCallbacks[key].push(func); + } +}); + +/** + * Extend the MultiColumnWizard with some static functions + */ +Object.append(MultiColumnWizard, +{ + // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) + operationLoadCallbacks: {}, + operationClickCallbacks: {}, + + /** + * Add a load callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key] = []; + } + + MultiColumnWizard.operationLoadCallbacks[key].push(func); + }, + + + /** + * Add a click callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key] = []; + } + + MultiColumnWizard.operationClickCallbacks[key].push(func); + }, + + + /** + * Operation "copy" - load + * @param Element the icon element + * @param Element the row + */ + copyLoad: function(el, row) + { + var rowCount = row.getSiblings().length; + + // remove the copy possibility if we have already reached maxCount + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "copy" - click + * @param Element the icon element + * @param Element the row + */ + copyClick: function(el, row) + { + var rowCount = row.getSiblings().length; + + // check maxCount for an inject + if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) + { + var copy = row.clone(); + copy.injectAfter(row); + + // update the row count + ++rowCount; + + this.updateOperations(); + this.updateFields.pass(rowCount, copy)(); + } + + // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - load + * @param Element the icon element + * @param Element the row + */ + deleteLoad: function(el, row) + { + var position = el.getAllPrevious().length - 1; + + // remove the delete possibility if necessary + if (this.options.minCount > 0 && position == this.options.minCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - click + * @param Element the icon element + * @param Element the row + */ + deleteClick: function(el, row) + { + row.destroy(); + }, + + + /** + * Operation "up" - click + * @param Element the icon element + * @param Element the row + */ + upClick: function(el, row) + { + if (row.getPrevious()) + { + row.injectBefore(row.getPrevious()); + } + }, + + + /** + * Operation "down" - click + * @param Element the icon element + * @param Element the row + */ + downClick: function(el, row) + { + if (row.getNext()) + { + row.injectAfter(row.getNext()); + } + } +}); + + +/** + * Register default callbacks + */ +//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); +MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.copyLoad); +MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); +MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); +MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); +MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); From a9aa315888ff416edfb2c28fc92abfd5a1de581a Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 19 Jan 2012 10:04:36 +0100 Subject: [PATCH 02/21] updated javascript class and prepared tableless mode (JS still only works with a table) --- .gitignore | 11 +- .../multicolumnwizard/MultiColumnWizard.php | 242 +++++--- .../html/js/multicolumnwizard_src.js | 522 +++++++++++------- .../html/js/multicolumnwizard_src_v2.js | 356 ------------ 4 files changed, 495 insertions(+), 636 deletions(-) delete mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js diff --git a/.gitignore b/.gitignore index ca859b3..4e855a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,11 @@ +# OS +.DS_Store +Thumbs.db -system/modules/multicolumnwizard/html/.DS_Store +# IDEs +.buildpath +.project +.settings/ +.build/ +.idea/ +nbproject/ diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index c3ab9d7..b3bb6f7 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -82,6 +82,12 @@ class MultiColumnWizard extends Widget implements uploadable */ protected $maxCount = 0; + /** + * Tableless + * @var boolean + */ + protected $blnTableless = false; + /** * Row specific data * @var array @@ -182,6 +188,10 @@ public function __set($strKey, $varValue) $this->maxCount = $varValue; break; + case 'generateTableless': + $this->blnTableless = $varValue; + break; + default: parent::__set($strKey, $varValue); break; @@ -355,34 +365,8 @@ public function generate() { continue; } - elseif ($arrField['eval']['columnPos']) - { - $arrHeaderItems[$arrField['eval']['columnPos']] = ''; - } - else - { - $arrHeaderItems[] = '' . ($arrField['label'][0] ? $arrField['label'][0] : $strKey) . ''; - } } - // Add label and return wizard - $return = ' -style) ? ('style="' . $this->style . '"') : ('')) . ' cellpadding="0" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard" summary="MultiColumnWizard">'; - - if ($this->columnTemplate == '') - { - $return .= ' - - - ' . implode("\n ", $arrHeaderItems) . ' - - - '; - } - - $return .=' - '; - $intNumberOfRows = max(count($this->varValue), 1); // always show the minimum number of rows if set @@ -396,7 +380,6 @@ public function generate() { $arrItem = array(); $strHidden = ''; - $return .= ''; // Walk every column foreach ($this->columnFields as $strKey => $arrField) @@ -524,60 +507,12 @@ public function generate() ); } } + } - // new array for items so we get rid of the ['entry'] and ['valign'] - $arrReturnItems = array(); - - if ($this->columnTemplate != '') - { - $objTemplate = new BackendTemplate($this->columnTemplate); - $objTemplate->items = $arrItem; - - $return .= ''; - } - else - { - foreach ($arrItem as $itemKey => $itemValue) - { - $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; - } - - $return .= implode('', $arrReturnItems); - } - - - - $return .= ''; - } - - $return .= '
' . $objTemplate->parse() . 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; - - // Add buttons - foreach ($this->arrButtons as $button => $image) - { - - if ($image === false) - { - continue; - } - - $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; - } - - $return .= '
'; - - $return .= ''; - - return $return; + return ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItem) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItem); } + /** * Initialize widget * @@ -714,7 +649,154 @@ public function addDataToFieldAtIndex($intIndex, $strField, $arrData) { $this->arrRowSpecificData[$intIndex][$strField] = $arrData; } + + + /** + * Generates a table formatted MCW + * @param array + * @param array + * @param string + * @param array + * @return string + */ + protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItem) + { + // generate header fields + foreach ($this->columnFields as $strKey => $arrField) + { + if ($arrField['eval']['columnPos']) + { + $arrHeaderItems[$arrField['eval']['columnPos']] = ''; + } + else + { + $arrHeaderItems[] = '' . ($arrField['label'][0] ? $arrField['label'][0] : $strKey) . ''; + } + } + + + $return = ' +style) ? ('style="' . $this->style . '"') : ('')) . 'rel="maxCount[' . ($this->maxCount ? $this->maxCount : '0') . '] minCount[' . ($this->minCount ? $this->minCount : '0') . '] unique[' . implode(',', $arrUnique) . '] datepicker[' . implode(',', $arrDatepicker) . ']" cellpadding="0" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard" summary="MultiColumnWizard">'; + + if ($this->columnTemplate == '') + { + $return .= ' + + + ' . implode("\n ", $arrHeaderItems) . ' + + + '; + } + + $return .=' + '; + + + // new array for items so we get rid of the ['entry'] and ['valign'] + $arrReturnItems = array(); + + if ($this->columnTemplate != '') + { + $objTemplate = new BackendTemplate($this->columnTemplate); + $objTemplate->items = $arrItem; + + $return .= ''; + } + else + { + foreach ($arrItem as $itemKey => $itemValue) + { + $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; + } + + $return .= implode('', $arrReturnItems); + } + + -} + $return .= ''; + $return .= '
' . $objTemplate->parse() . 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + + $return .= $this->generateButtonString(); + + $return .= '
'; + + $return .= ''; + + return $return; + } + + + /** + * Generates a div formatted MCW + * @param array + * @param array + * @param string + * @param array + * @return string + */ + protected function generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItem) + { + // generate header fields + foreach ($this->columnFields as $strKey => $arrField) + { + $arrHeaderItems[] = sprintf('
%s
', $strKey, ($arrField['label'][0] ? $arrField['label'][0] : $strKey)); + } + + + $return = 'style) ? (' style="' . $this->style . '"') : '') . ' rel="maxCount[' . ($this->maxCount ? $this->maxCount : '0') . '] minCount[' . ($this->minCount ? $this->minCount : '0') . '] unique[' . implode(',', $arrUnique) . '] datepicker[' . implode(',', $arrDatepicker) . ']" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard">'; + $return .= '
' . implode('', $arrHeaderItems) . '
'; + + + + // new array for items so we get rid of the ['entry'] and ['valign'] + $arrReturnItems = array(); + + foreach ($arrItem as $itemKey => $itemValue) + { + $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; + } + + $return .= implode('', $arrReturnItems); + + + + $return .= '
' . $this->generateButtonString() . '
'; + + $return .= $strHidden; + + return $return . ''; + } + + + /** + * Generate button string + * @return string + */ + protected function generateButtonString() + { + $return = ''; + + // Add buttons + foreach ($this->arrButtons as $button => $image) + { + + if ($image === false) + { + continue; + } + + $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + } -?> + return $return; + } +} \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js index 80d28f0..241f9d0 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js @@ -24,214 +24,338 @@ * @license http://opensource.org/licenses/lgpl-3.0.html */ -var MultiColumnWizard = +var MultiColumnWizard = new Class( { - execHOOK: Array(), - - 'execute': function(el, command, id) - { - stopEvent = new Event(window.event); - stopEvent.preventDefault(); - - var table = $(id); - var tbody = table.getFirst().getNext(); - var parent = $(el).getParent('tr'); - var options = { - 'maxCount': table.getProperty('rel').match(/maxCount\[[0-9]+\]/ig)[0].replace('maxCount[','').replace(']','').toInt(), - 'minCount': table.getProperty('rel').match(/minCount\[[0-9]+\]/ig)[0].replace('minCount[','').replace(']','').toInt(), - 'uniqueFields': table.getProperty('rel').match(/unique\[[a-z0-9,]*\]/ig)[0].replace('unique[','').replace(']','').split(',') - }; - - // Do not run this in the frontend, Backend class would not be available - if (window.Backend) - { - Backend.getScrollOffset(); - } - - - // Execute the command - MultiColumnWizard[command](tbody,parent,options); - - - // set name attribute to a dummy to avoid duplicate names - tbody.getElements('input[type=radio], input[type=checkbox]').each(function(el,i){ - if(typeof el.get('name') == 'string') - el.set('name', el.get('name')+'DUMMYNAME'+i); - }); + Implements: [Options], + options: + { + table: null, + maxCount: 0, + minCount: 0, + uniqueFields: [] + }, + + // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) + operationLoadCallbacks: [], + operationClickCallbacks: [], + + /** + * Initialize the wizard + * @param Object options + */ + initialize: function(options) + { + this.setOptions(options); - // rewrite attributes - tbody.getChildren().each(function(el,i){ - MultiColumnWizard.updateFields(el.getChildren(), i) - }); + // make sure we really have the table as element + this.options.table = document.id(this.options.table); + + // Do not run this in the frontend, Backend class would not be available + if (window.Backend) + { + Backend.getScrollOffset(); + } + + this.updateOperations(); + }, + + + /** + * Update operations + */ + updateOperations: function() + { + var self = this; - // kill dummy names - tbody.getElements('input[type=radio], input[type=checkbox]').each(function(el,i){ - if(typeof el.get('name') == 'string') - el.set('name', el.get('name').replace('DUMMYNAME'+i,'')); + // execute load callback and register click event callback + this.options.table.getElement('tbody').getElements('tr').each(function(el, index) + { + el.getElement('td.operations').getElements('a').each(function(operation) + { + var key = operation.get('rel'); + + // register static load callbacks + if (MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // register instance load callbacks + if (self.operationLoadCallbacks[key]) + { + self.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // remove all click events + operation.removeEvents('click'); + + // register static click callbacks + if (MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); }); + }); + } + + // register instance click callbacks + if (self.operationClickCallbacks[key]) + { + self.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + self.updateFields(index); + }); + }); + } + }); }); + }, + + /** + * Update row attributes + * @param int level + * @param element row + * @return element the updated element + */ + updateRowAttributes: function(level, row) + { + // this in this context refers to the row element + row.getElements('.mcwUpdateFields *[name]').each(function(el) + { + // rewrite elements name + if (typeOf(el.getProperty('name')) == 'string') + { + var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); + if (erg) + { + el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); + } + } - // HOOK for other extensions like Autocompleter or Chosen - for(var i=0; i 1 || options.uniqueFields[0] != '') - { - for(var i=0; i 1) - { - parent.destroy(); - } - else - { - var childs = parent.getElements('input,select,textarea'); - for (var i=0; i tbody.getChildren().length ) - { - tbody.getElements('img[src=system/themes/default/images/copy.gif]').getParent().setStyle('display', 'inline'); - } - - if (options.minCount >= tbody.getChildren().length ) - { - tbody.getElements('img[src=system/themes/default/images/delete.gif]').getParent().setStyle('display', 'none'); - } - }, + // rewrite elements id + if (typeOf(el.getProperty('id')) == 'string') + { + var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); + } + } + // rewrite elements for + if (typeOf(el.getProperty('for')) == 'string') + { + var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); + } + } + }); + + return row; + }, + + /** - * Rewrite ID,NAME,FOR attributes - * for the fields + * Add a load callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback */ - updateFields: function(arrEl, level) - { - arrEl.each(function(el) - { - // also update the childs of this element - if (el.getChildren().length > 0) - { - MultiColumnWizard.updateFields(el.getChildren(), level); - } - - // rewrite elements name - if(typeof el.get('name') == 'string') - { - var erg = el.get('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); - if(erg) el.set('name', erg[1]+'['+level+']'+erg[3]); - } - // rewrite elements id - if(typeof el.get('id') == 'string') - { - var erg = el.get('id').match(/^(.+)_row[0-9]+_(.+)$/i); - if(erg) el.set('id', erg[1]+'_row'+level+'_'+erg[2]); - } - // rewrite elements for - if(typeof el.get('for') == 'string') - { - var erg = el.get('for').match(/^(.+)_row[0-9]+_(.+)$/i); - if(erg) el.set('for', erg[1]+'_row'+level+'_'+erg[2]); - } - - }); - }, - - clearElementValue: function(el) - { - if (el.get('type') == 'checkbox' || el.get('type') == 'radio') - { - el.checked = false; - } - else - { - el.set('value', ''); - } - }, - - - attachDatepicker: function(el, command, id) - { - // only if a new element is created - if(command != 'copy') return; - - // get datepicker-fields from table-options - var datepickerFields = $(id).getProperty('rel').match(/datepicker\[[a-z0-9,]*\]/ig)[0].replace('datepicker[','').replace(']','').split(','); - var rows = $(id).getElement('tbody').getChildren(); + addOperationLoadCallback: function(key, func) + { + if (!this.operationLoadCallbacks[key]) + { + this.operationLoadCallbacks[key] = []; + } - // reattach - if (datepickerFields.length > 1 || datepickerFields[0] != '') - { - for(var i=0; i...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!this.operationClickCallbacks[key]) + { + this.operationClickCallbacks[key] = []; } - } -}; + + this.operationClickCallbacks[key].push(func); + } +}); -// Register attachTatepicker callback -MultiColumnWizard.execHOOK.push(MultiColumnWizard.attachDatepicker); +/** + * Extend the MultiColumnWizard with some static functions + */ +Object.append(MultiColumnWizard, +{ + // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) + operationLoadCallbacks: {}, + operationClickCallbacks: {}, + + /** + * Add a load callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key] = []; + } + + MultiColumnWizard.operationLoadCallbacks[key].push(func); + }, + + + /** + * Add a click callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key] = []; + } + + MultiColumnWizard.operationClickCallbacks[key].push(func); + }, + + + /** + * Operation "copy" - load + * @param Element the icon element + * @param Element the row + */ + copyLoad: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // remove the copy possibility if we have already reached maxCount + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "copy" - click + * @param Element the icon element + * @param Element the row + */ + copyClick: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // check maxCount for an inject + if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) + { + // update the row count + ++rowCount; + + var copy = row.clone(); + + // calculate -1 because the attributes start with 0, right? ;-) + copy = this.updateRowAttributes(rowCount-1, copy); + copy.inject(row, 'after'); + this.updateOperations(); + } + + // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - load + * @param Element the icon element + * @param Element the row + */ + deleteLoad: function(el, row) + { + var position = el.getAllPrevious().length - 1; + + // remove the delete possibility if necessary + if (this.options.minCount > 0 && position == this.options.minCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - click + * @param Element the icon element + * @param Element the row + */ + deleteClick: function(el, row) + { + row.destroy(); + }, + + + /** + * Operation "up" - click + * @param Element the icon element + * @param Element the row + */ + upClick: function(el, row) + { + if (row.getPrevious()) + { + row.injectBefore(row.getPrevious()); + } + }, + + + /** + * Operation "down" - click + * @param Element the icon element + * @param Element the row + */ + downClick: function(el, row) + { + if (row.getNext()) + { + row.injectAfter(row.getNext()); + } + } +}); + + +/** + * Register default callbacks + */ +//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); +MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.copyLoad); +MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); +MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); +MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); +MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js deleted file mode 100644 index 29b28bb..0000000 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js +++ /dev/null @@ -1,356 +0,0 @@ -/** - * Contao Open Source CMS - * Copyright (C) 2005-2011 Leo Feyer - * - * Formerly known as TYPOlight Open Source CMS. - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program. If not, please visit the Free - * Software Foundation website at . - * - * PHP version 5 - * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 - * @package MultiColumnWizard - * @license http://opensource.org/licenses/lgpl-3.0.html - */ - -var MultiColumnWizard = new Class( -{ - Implements: [Options], - options: - { - table: null, - maxCount: 0, - minCount: 0, - uniqueFields: [] - }, - - // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) - operationLoadCallbacks: [], - operationClickCallbacks: [], - - /** - * Initialize the wizard - * @param Object options - */ - initialize: function(options) - { - this.setOptions(options); - - // make sure we really have the table as element - this.options.table = document.id(this.options.table); - - // Do not run this in the frontend, Backend class would not be available - if (window.Backend) - { - Backend.getScrollOffset(); - } - - this.updateOperations(); - }, - - - /** - * Update operations - */ - updateOperations: function() - { - var self = this; - - // execute load callback and register click event callback - this.options.table.getElement('tbody').getElements('tr').each(function(el, index) - { - el.getElement('td.operations').getElements('a').each(function(operation) - { - var key = operation.get('rel'); - - // register static load callbacks - if (MultiColumnWizard.operationLoadCallbacks[key]) - { - MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) - { - callback.pass([operation, el], self)(); - }); - } - - // register instance load callbacks - if (self.operationLoadCallbacks[key]) - { - self.operationLoadCallbacks[key].each(function(callback) - { - callback.pass([operation, el], self)(); - }); - } - - // remove all click events - operation.removeEvents('click'); - - // register static click callbacks - if (MultiColumnWizard.operationClickCallbacks[key]) - { - MultiColumnWizard.operationClickCallbacks[key].each(function(callback) - { - operation.addEvent('click', function(e) - { - e.preventDefault(); - callback.pass([operation, el], self)(); }); - }); - } - - // register instance click callbacks - if (self.operationClickCallbacks[key]) - { - self.operationClickCallbacks[key].each(function(callback) - { - operation.addEvent('click', function(e) - { - e.preventDefault(); - callback.pass([operation, el], self)(); - self.updateFields(index); - }); - }); - } - }); - }); - }, - - - /** - * Update fields - * @param int level - */ - updateFields: function(level) - { - // this in this context refers to the row element - this.getElements('.mcwUpdateFields *[name]').each(function(el) - { - // rewrite elements name - if (typeOf(el.getProperty('name')) == 'string') - { - var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); - if (erg) - { - el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); - } - } - - // rewrite elements id - if (typeOf(el.getProperty('id')) == 'string') - { - var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); - if (erg) - { - el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); - } - } - - // rewrite elements for - if (typeOf(el.getProperty('for')) == 'string') - { - var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); - if (erg) - { - el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); - } - } - }); - }, - - - /** - * Add a load callback for the instance - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationLoadCallback: function(key, func) - { - if (!this.operationLoadCallbacks[key]) - { - this.operationLoadCallbacks[key] = []; - } - - this.operationLoadCallbacks[key].push(func); - }, - - - /** - * Add a click callback for the instance - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationClickCallback: function(key, func) - { - if (!this.operationClickCallbacks[key]) - { - this.operationClickCallbacks[key] = []; - } - - this.operationClickCallbacks[key].push(func); - } -}); - -/** - * Extend the MultiColumnWizard with some static functions - */ -Object.append(MultiColumnWizard, -{ - // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) - operationLoadCallbacks: {}, - operationClickCallbacks: {}, - - /** - * Add a load callback for all the MCW's - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationLoadCallback: function(key, func) - { - if (!MultiColumnWizard.operationLoadCallbacks[key]) - { - MultiColumnWizard.operationLoadCallbacks[key] = []; - } - - MultiColumnWizard.operationLoadCallbacks[key].push(func); - }, - - - /** - * Add a click callback for all the MCW's - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationClickCallback: function(key, func) - { - if (!MultiColumnWizard.operationClickCallbacks[key]) - { - MultiColumnWizard.operationClickCallbacks[key] = []; - } - - MultiColumnWizard.operationClickCallbacks[key].push(func); - }, - - - /** - * Operation "copy" - load - * @param Element the icon element - * @param Element the row - */ - copyLoad: function(el, row) - { - var rowCount = row.getSiblings().length; - - // remove the copy possibility if we have already reached maxCount - if (this.options.maxCount > 0 && rowCount == this.options.maxCount) - { - el.destroy(); - } - }, - - - /** - * Operation "copy" - click - * @param Element the icon element - * @param Element the row - */ - copyClick: function(el, row) - { - var rowCount = row.getSiblings().length; - - // check maxCount for an inject - if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) - { - var copy = row.clone(); - copy.injectAfter(row); - - // update the row count - ++rowCount; - - this.updateOperations(); - this.updateFields.pass(rowCount, copy)(); - } - - // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) - if (this.options.maxCount > 0 && rowCount == this.options.maxCount) - { - el.destroy(); - } - }, - - - /** - * Operation "delete" - load - * @param Element the icon element - * @param Element the row - */ - deleteLoad: function(el, row) - { - var position = el.getAllPrevious().length - 1; - - // remove the delete possibility if necessary - if (this.options.minCount > 0 && position == this.options.minCount) - { - el.destroy(); - } - }, - - - /** - * Operation "delete" - click - * @param Element the icon element - * @param Element the row - */ - deleteClick: function(el, row) - { - row.destroy(); - }, - - - /** - * Operation "up" - click - * @param Element the icon element - * @param Element the row - */ - upClick: function(el, row) - { - if (row.getPrevious()) - { - row.injectBefore(row.getPrevious()); - } - }, - - - /** - * Operation "down" - click - * @param Element the icon element - * @param Element the row - */ - downClick: function(el, row) - { - if (row.getNext()) - { - row.injectAfter(row.getNext()); - } - } -}); - - -/** - * Register default callbacks - */ -//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); -MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.copyLoad); -MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); -MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); -MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); -MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); -MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); From 0d096aee2b02247fa5caca68a8f7d5b631ec138f Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 19 Jan 2012 10:07:22 +0100 Subject: [PATCH 03/21] fixed js dev path --- system/modules/multicolumnwizard/MultiColumnWizard.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index b3bb6f7..6ed4737 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -302,7 +302,8 @@ public function generate() $this->columnFields = $this->{$this->arrCallback[0]}->{$this->arrCallback[1]}($this); } - $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_src_v2.js'; + // TODO: minify this and change path + $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js'; $GLOBALS['TL_CSS'][] = 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; $strCommand = 'cmd_' . $this->strField; From 7cd24fd3123d690ee7755ed08a50cc7d300c5edd Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 19 Jan 2012 10:11:40 +0100 Subject: [PATCH 04/21] fixed missing class "operations" --- system/modules/multicolumnwizard/MultiColumnWizard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index 6ed4737..597e5ad 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -716,7 +716,7 @@ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrIte - $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; $return .= $this->generateButtonString(); From be067b8c5e3f5c5eb1ffcd994599d7133667e7a4 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 19 Jan 2012 11:08:45 +0100 Subject: [PATCH 05/21] also update the label's "for" attribute --- .../multicolumnwizard/html/js/multicolumnwizard_src.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js index 241f9d0..bc4b999 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js @@ -103,7 +103,8 @@ var MultiColumnWizard = new Class( operation.addEvent('click', function(e) { e.preventDefault(); - callback.pass([operation, el], self)(); }); + callback.pass([operation, el], self)(); + }); }); } @@ -133,7 +134,6 @@ var MultiColumnWizard = new Class( */ updateRowAttributes: function(level, row) { - // this in this context refers to the row element row.getElements('.mcwUpdateFields *[name]').each(function(el) { // rewrite elements name @@ -155,7 +155,10 @@ var MultiColumnWizard = new Class( el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); } } + }); + row.getElements('.mcwUpdateFields label').each(function(el) + { // rewrite elements for if (typeOf(el.getProperty('for')) == 'string') { From a98a5356925324e6af08e9974a02122137b8ddff Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 19 Jan 2012 11:09:12 +0100 Subject: [PATCH 06/21] fixed not all item being displayed --- .../multicolumnwizard/MultiColumnWizard.php | 58 ++++++++----------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index 597e5ad..d9d9ddf 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -375,11 +375,12 @@ public function generate() { $intNumberOfRows = $this->minCount; } + + $arrItems = array(); // Add input fields for ($i = 0; $i < $intNumberOfRows; $i++) { - $arrItem = array(); $strHidden = ''; // Walk every column @@ -494,13 +495,13 @@ public function generate() // Build array of items if ($arrField['eval']['columnPos'] != '') { - $arrItem[$objWidget->columnPos]['entry'] .= $strWidget; - $arrItem[$objWidget->columnPos]['valign'] = $arrField['eval']['valign']; - $arrItem[$objWidget->columnPos]['tl_class'] = $arrField['eval']['tl_class']; + $arrItems[$i][$objWidget->columnPos]['entry'] .= $strWidget; + $arrItems[$i][$objWidget->columnPos]['valign'] = $arrField['eval']['valign']; + $arrItems[$i][$objWidget->columnPos]['tl_class'] = $arrField['eval']['tl_class']; } else { - $arrItem[$strKey] = array + $arrItems[$i][$strKey] = array ( 'entry' => $strWidget, 'valign' => $arrField['eval']['valign'], @@ -510,7 +511,9 @@ public function generate() } } - return ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItem) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItem); + print_r(array_values($arrItem)); + + return ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems); } @@ -660,7 +663,7 @@ public function addDataToFieldAtIndex($intIndex, $strField, $arrData) * @param array * @return string */ - protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItem) + protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems) { // generate header fields foreach ($this->columnFields as $strKey => $arrField) @@ -691,36 +694,23 @@ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrIte } $return .=' - '; - - - // new array for items so we get rid of the ['entry'] and ['valign'] - $arrReturnItems = array(); - - if ($this->columnTemplate != '') - { - $objTemplate = new BackendTemplate($this->columnTemplate); - $objTemplate->items = $arrItem; + '; - $return .= '' . $objTemplate->parse() . ''; - } - else + foreach ($arrItems as $k => $arrValue) { - foreach ($arrItem as $itemKey => $itemValue) - { - $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; - } - - $return .= implode('', $arrReturnItems); + $return .= ''; + foreach ($arrValue as $itemKey => $itemValue) + { + $return .= '' . $itemValue['entry'] . ''; + } + + // insert buttons at the very end + $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + $return .= $this->generateButtonString(); + $return .= ''; + $return .= ''; } - - - $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; - - $return .= $this->generateButtonString(); - - $return .= ''; $return .= ''; $return .= ''; */ - $datepicker = ''; + /* $datepicker = ''; +';*/ } // Add custom wizard @@ -664,6 +665,7 @@ public function addDataToFieldAtIndex($intIndex, $strField, $arrData) */ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems) { + // generate header fields foreach ($this->columnFields as $strKey => $arrField) { @@ -705,7 +707,7 @@ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrIte // insert buttons at the very end $return .= 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; - $return .= $this->generateButtonString(); + $return .= $this->generateButtonString($k); $return .= ''; $return .= ''; } @@ -759,7 +761,7 @@ protected function generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems - $return .= '
' . $this->generateButtonString() . '
'; + $return .= '
' . $this->generateButtonString($strKey) . '
'; $return .= $strHidden; @@ -771,22 +773,22 @@ protected function generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems * Generate button string * @return string */ - protected function generateButtonString() + protected function generateButtonString($level = 0) { - $return = ''; - - // Add buttons - foreach ($this->arrButtons as $button => $image) - { + $return = ''; - if ($image === false) + // Add buttons + foreach ($this->arrButtons as $button => $image) { - continue; + + if ($image === false) + { + continue; + } + + $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; } - - $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; - } - return $return; - } + return $return; + } } \ No newline at end of file diff --git a/system/modules/multicolumnwizard/MultiColumnWizardHelper.php b/system/modules/multicolumnwizard/MultiColumnWizardHelper.php deleted file mode 100644 index 051f08b..0000000 --- a/system/modules/multicolumnwizard/MultiColumnWizardHelper.php +++ /dev/null @@ -1,91 +0,0 @@ -. - * - * PHP version 5 - * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 - * @package MultiColumnWizard - * @license LGPL - * @filesource - */ - -class MultiColumnWizardHelper extends System -{ - - /** - * Static helper method to get all the data from a certain key for all the rows - * @param string - * @param string - * @return array - */ - public static function getByKey($strSerialized, $strKey) - { - $arrData = deserialize($strSerialized); - $arrReturnData = array(); - - foreach ($arrData as $rowKey => $rowData) - { - $arrReturnData[] = $rowData['values'][$strKey]; - } - - return $arrReturnData; - } - - /** - * Static helper method to get all the data from a certain key for all the rows that match a certain other row key - * @param string - * @param string - * @param array - * @return array - */ - public static function getFilteredByKey($strSerialized, $strKey, $arrConditions) - { - $arrData = deserialize($strSerialized); - $intCountConditions = count($arrConditions); - - $arrReturnData = array(); - - foreach ($arrData as $rowKey => $rowData) - { - $intMeetCondition = 0; - - // check data for every filter - foreach ($arrConditions as $column => $value) - { - if ($rowData['values'][$column] == $value) - { - $intMeetCondition++; - } - } - - // check if the value meets ALL conditions (AND condition) - if ($intMeetCondition == $intCountConditions) - { - $arrReturnData[] = $rowData['values'][$strKey]; - } - } - - return $arrReturnData; - } - -} - -?> \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js index 984a29d..7c0503d 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js @@ -73,7 +73,7 @@ var MultiColumnWizard = new Class( el.getElement('td.operations').getElements('a').each(function(operation) { var key = operation.get('rel'); - + // register static load callbacks if (MultiColumnWizard.operationLoadCallbacks[key]) { @@ -134,7 +134,8 @@ var MultiColumnWizard = new Class( */ updateRowAttributes: function(level, row) { - row.getElements('.mcwUpdateFields *[name]').each(function(el) + + row.getElements('.mcwUpdateFields *').each(function(el) { // rewrite elements name if (typeOf(el.getProperty('name')) == 'string') @@ -142,6 +143,7 @@ var MultiColumnWizard = new Class( var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); if (erg) { + el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); } } @@ -149,10 +151,30 @@ var MultiColumnWizard = new Class( // rewrite elements id if (typeOf(el.getProperty('id')) == 'string') { + var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); if (erg) { el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); + + //make input field visible again, if some js made set display:none + if (el.nodeName == 'INPUT' && el.getProperty('style').search('none;') > 0) el.setProperty('style','display: inline;'); + } + } + else + { + //eliminate input fields without an id -> this iput field was created by JS (i hope so :)) + if (el.nodeName == 'INPUT') el.destroy(); + } + + // rewrite elements onclick (e.g. pagePicker) + if (typeOf(el.getProperty('onclick')) == 'string') + { + var erg = el.getProperty('onclick').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + + el.setProperty('onclick', erg[1] + '_row' + level + '_' + erg[2]); } } }); @@ -165,10 +187,32 @@ var MultiColumnWizard = new Class( var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); if (erg) { + el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); } } }); + + // modify inline scripts + row.getElements('.mcwUpdateFields script').each(function(el) + { + //ToDO: refactor this part. For some reason replace will only find the first token of _row[0-9]+_ + var newScript = ''; + var script = el.get('html').toString(); + var length = 0; + var start = script.search(/_row[0-9]+_/i); + while(start > 0) + { + + length = script.match(/(_row[0-9]+)+_/i)[0].length; + newScript = newScript + script.substr(0, start) + '_row' + level + '_'; + script = script.substr(start + length); + start = script.search(/_row[0-9]+_/i); + } + + el.set('html', newScript+script); + + }); return row; }, @@ -257,10 +301,12 @@ Object.append(MultiColumnWizard, var rowCount = row.getSiblings().length + 1; // remove the copy possibility if we have already reached maxCount - if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + if (this.options.maxCount > 0 && rowCount >= this.options.maxCount) { - el.destroy(); - } + el.setStyle('display', 'none'); + }else{ + el.setStyle('display', 'inline'); + } }, @@ -271,6 +317,7 @@ Object.append(MultiColumnWizard, */ copyClick: function(el, row) { + var rowCount = row.getSiblings().length + 1; // check maxCount for an inject @@ -283,14 +330,21 @@ Object.append(MultiColumnWizard, copy = this.updateRowAttributes(rowCount-1, copy); copy.injectAfter(row); - - this.addOperationClickCallback('click', this.updateOperations); + //exec script + if (copy.getElements('script').length > 0) + { + copy.getElements('script').each(function(script){ + $exec(script.get('html')); + }); + } + this.addOperationClickCallback('click', this.updateOperations()); } // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) if (this.options.maxCount > 0 && rowCount == this.options.maxCount) - { - el.destroy(); + { + row.getSiblings().getElements('a[rel="copy"]').each(function(e){e.setStyle('display', 'none')}); + el.setStyle('display', 'none'); } }, @@ -302,13 +356,17 @@ Object.append(MultiColumnWizard, */ deleteLoad: function(el, row) { - var position = el.getAllPrevious().length - 1; - + var rowCount = row.getSiblings().length + 1; + // remove the delete possibility if necessary - if (this.options.minCount > 0 && position == this.options.minCount) + if (this.options.minCount > 0 && rowCount <= this.options.minCount) { - el.destroy(); + el.setStyle('display', 'none'); } + else + { + el.setStyle('display', 'inline'); + } }, @@ -318,9 +376,23 @@ Object.append(MultiColumnWizard, * @param Element the row */ deleteClick: function(el, row) - { - row.destroy(); - }, + { + //get all following rows + var rows = row.getAllNext(); + //extract the current level + level = row.getElements('.mcwUpdateFields *[name]')[0].getProperty('id').match(/_row[0-9]+_/i)[0].match(/[0-9]+/i)[0]; + //destroy current row + row.destroy(); + + var that = this; + //update index of following rows + rows.each(function(row){ + that.updateRowAttributes(level++, row); + }); + + this.addOperationClickCallback('click', this.updateOperations()); + + }, /** From 8cee7e4c433a4587864b71f27d5f60abc60eeadb Mon Sep 17 00:00:00 2001 From: David Maack Date: Thu, 19 Apr 2012 18:07:45 +0200 Subject: [PATCH 15/21] Fixed issues #40 and #46 Added Choosen-Support for Contao 2.11 Splitted JS-File for BE and FE Changed Callback handling: LoadCallback are only executed oat the load of the MCW, after the clickCallbacks are finished, the updateOptions() will be executed and the new UpdateCallbacks are triggered. --- .../multicolumnwizard/MultiColumnWizard.php | 271 ++++++--- .../html/js/multicolumnwizard.js | 1 - .../html/js/multicolumnwizard_be_src.js | 555 ++++++++++++++++++ .../html/js/multicolumnwizard_fe_src.js | 389 ++++++++++++ .../html/js/multicolumnwizard_src.js | 460 --------------- 5 files changed, 1118 insertions(+), 558 deletions(-) delete mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard.js create mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js create mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js delete mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index 60af7f7..a8f384d 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -1,4 +1,5 @@ -import('Database'); @@ -302,8 +304,8 @@ public function generate() $this->columnFields = $this->{$this->arrCallback[0]}->{$this->arrCallback[1]}($this); } - // TODO: minify this and change path - $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js'; + // TODO: minify this and change path + $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_' . strtolower(TL_MODE) . '_src.js'; $GLOBALS['TL_CSS'][] = 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; $this->strCommand = 'cmd_' . $this->strField; @@ -376,8 +378,8 @@ public function generate() { $intNumberOfRows = $this->minCount; } - - $arrItems = array(); + + $arrItems = array(); // Add input fields for ($i = 0; $i < $intNumberOfRows; $i++) @@ -438,15 +440,15 @@ public function generate() case 'time': $time = ",\n timePickerOnly:true"; break; - + default: $time = ''; break; } - $datepicker = ' + $datepicker = ' '; + + $datepicker = $this->getMcWDatePickerString($objWidget->id, $strKey, $rgxp); + + /* $datepicker = ''; - /* $datepicker = '';*/ + '; */ } // Add custom wizard @@ -510,12 +515,85 @@ public function generate() ); } } - } + } - return ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems); + return ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems); } + protected function getMcWDatePickerString($strId, $strKey, $rgxp) + { + if (version_compare(VERSION, '2.11', '<')) + { + $format = $GLOBALS['TL_CONFIG'][$rgxp . 'Format']; + switch ($rgxp) + { + case 'datim': + $time = ",\n timePicker:true"; + break; + + case 'time': + $time = ",\n timePickerOnly:true"; + break; + + default: + $time = ''; + break; + } + + return ' + '; + } + else + { + $format = Date::formatToJs($GLOBALS['TL_CONFIG'][$rgxp . 'Format']); + switch ($rgxp) + { + case 'datim': + $time = ",\n timePicker:true"; + break; + + case 'time': + $time = ",\n pickOnly:\"time\""; + break; + + default: + $time = ''; + break; + } + return ' + '; + } + } /** * Initialize widget @@ -615,8 +693,8 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) $arrField['eval']['tl_class'] = trim($arrField['eval']['tl_class'] . ' hidelabel'); } - // add class to enable easy updating of "name" attributes etc. - $arrField['eval']['tl_class'] = trim($arrField['eval']['tl_class'] . ' mcwUpdateFields'); + // add class to enable easy updating of "name" attributes etc. + $arrField['eval']['tl_class'] = trim($arrField['eval']['tl_class'] . ' mcwUpdateFields'); // load callback if (is_array($arrField['load_callback'])) @@ -653,22 +731,22 @@ public function addDataToFieldAtIndex($intIndex, $strField, $arrData) { $this->arrRowSpecificData[$intIndex][$strField] = $arrData; } - - - /** - * Generates a table formatted MCW - * @param array - * @param array - * @param string - * @param array - * @return string - */ - protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems) - { - - // generate header fields + + /** + * Generates a table formatted MCW + * @param array + * @param array + * @param string + * @param array + * @return string + */ + protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems) + { + + // generate header fields foreach ($this->columnFields as $strKey => $arrField) { + if ($arrField['eval']['columnPos']) { $arrHeaderItems[$arrField['eval']['columnPos']] = ''; @@ -678,8 +756,8 @@ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrIte $arrHeaderItems[] = '' . ($arrField['label'][0] ? $arrField['label'][0] : $strKey) . ''; } } - - + + $return = ' style) ? ('style="' . $this->style . '"') : ('')) . 'rel="maxCount[' . ($this->maxCount ? $this->maxCount : '0') . '] minCount[' . ($this->minCount ? $this->minCount : '0') . '] unique[' . implode(',', $arrUnique) . '] datepicker[' . implode(',', $arrDatepicker) . ']" cellpadding="0" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard" summary="MultiColumnWizard">'; @@ -697,24 +775,24 @@ protected function generateTable($arrUnique, $arrDatepicker, $strHidden, $arrIte $return .=' '; - foreach ($arrItems as $k => $arrValue) + foreach ($arrItems as $k => $arrValue) { - $return .= ''; - foreach ($arrValue as $itemKey => $itemValue) - { - $return .= '' . $itemValue['entry'] . ''; - } - - // insert buttons at the very end - $return .= ''; - $return .= ''; + $return .= ''; + foreach ($arrValue as $itemKey => $itemValue) + { + $return .= '' . $itemValue['entry'] . ''; + } + + // insert buttons at the very end + $return .= ''; + $return .= ''; } - $return .= '
buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; - $return .= $this->generateButtonString($k); - $return .= '
buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + $return .= $this->generateButtonString($k); + $return .= '
'; - - $return .= ''; - return $return; - } - - - /** - * Generates a div formatted MCW - * @param array - * @param array - * @param string - * @param array - * @return string - */ - protected function generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) - { - // generate header fields + return $return; + } + + /** + * Generates a div formatted MCW + * @param array + * @param array + * @param string + * @param array + * @return string + */ + protected function generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) + { + // generate header fields foreach ($this->columnFields as $strKey => $arrField) { - $arrHeaderItems[] = sprintf('
%s
', $strKey, ($arrField['label'][0] ? $arrField['label'][0] : $strKey)); + $arrHeaderItems[] = sprintf('
%s
', $strKey, ($arrField['label'][0] ? $arrField['label'][0] : $strKey)); } - - + + $return = 'style) ? (' style="' . $this->style . '"') : '') . ' rel="maxCount[' . ($this->maxCount ? $this->maxCount : '0') . '] minCount[' . ($this->minCount ? $this->minCount : '0') . '] unique[' . implode(',', $arrUnique) . '] datepicker[' . implode(',', $arrDatepicker) . ']" id="ctrl_' . $this->strId . '" class="tl_modulewizard multicolumnwizard">'; $return .= '
' . implode('', $arrHeaderItems) . '
'; - - + + // new array for items so we get rid of the ['entry'] and ['valign'] $arrReturnItems = array(); - foreach ($arrItem as $itemKey => $itemValue) + foreach ($arrItem as $itemKey => $itemValue) { $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; } - $return .= implode('', $arrReturnItems); + $return .= implode('', $arrReturnItems); $return .= '
' . $this->generateButtonString($strKey) . '
'; - - $return .= $strHidden; - - return $return . ''; - } - - - /** - * Generate button string - * @return string - */ - protected function generateButtonString($level = 0) - { - $return = ''; - - // Add buttons - foreach ($this->arrButtons as $button => $image) - { - if ($image === false) - { - continue; - } + $return .= $strHidden; + + return $return . ''; + } - $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + /** + * Generate button string + * @return string + */ + protected function generateButtonString($level = 0) + { + $return = ''; + + // Add buttons + foreach ($this->arrButtons as $button => $image) + { + + if ($image === false) + { + continue; } - return $return; - } + $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + } + + return $return; + } + } \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard.js deleted file mode 100644 index d9c26e3..0000000 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard.js +++ /dev/null @@ -1 +0,0 @@ -var MultiColumnWizard={execHOOK:Array(),execute:function(e,g,h){stopEvent=new Event(window.event);stopEvent.preventDefault();var f=$(h);var b=f.getFirst().getNext();var d=$(e).getParent("tr");var a={maxCount:f.getProperty("rel").match(/maxCount\[[0-9]+\]/ig)[0].replace("maxCount[","").replace("]","").toInt(),minCount:f.getProperty("rel").match(/minCount\[[0-9]+\]/ig)[0].replace("minCount[","").replace("]","").toInt(),uniqueFields:f.getProperty("rel").match(/unique\[[a-z0-9,]*\]/ig)[0].replace("unique[","").replace("]","").split(",")};if(window.Backend){Backend.getScrollOffset()}MultiColumnWizard[g](b,d,a);b.getElements("input[type=radio], input[type=checkbox]").each(function(k,j){if(typeof k.get("name")=="string"){k.set("name",k.get("name")+"DUMMYNAME"+j)}});b.getChildren().each(function(k,j){MultiColumnWizard.updateFields(k.getChildren(),j)});b.getElements("input[type=radio], input[type=checkbox]").each(function(k,j){if(typeof k.get("name")=="string"){k.set("name",k.get("name").replace("DUMMYNAME"+j,""))}});for(var c=0;c1||a.uniqueFields[0]!=""){for(var c=0;c1){d.destroy()}else{var e=d.getElements("input,select,textarea");for(var c=0;cb.getChildren().length){b.getElements("img[src=system/themes/default/images/copy.gif]").getParent().setStyle("display","inline")}if(a.minCount>=b.getChildren().length){b.getElements("img[src=system/themes/default/images/delete.gif]").getParent().setStyle("display","none")}},updateFields:function(a,b){a.each(function(c){if(c.getChildren().length>0){MultiColumnWizard.updateFields(c.getChildren(),b)}if(typeof c.get("name")=="string"){var d=c.get("name").match(/^([^\[]+)\[([0-9]+)\](.*)$/i);if(d){c.set("name",d[1]+"["+b+"]"+d[3])}}if(typeof c.get("id")=="string"){var d=c.get("id").match(/^(.+)_row[0-9]+_(.+)$/i);if(d){c.set("id",d[1]+"_row"+b+"_"+d[2])}}if(typeof c.get("for")=="string"){var d=c.get("for").match(/^(.+)_row[0-9]+_(.+)$/i);if(d){c.set("for",d[1]+"_row"+b+"_"+d[2])}}})},clearElementValue:function(a){if(a.get("type")=="checkbox"||a.get("type")=="radio"){a.checked=false}else{a.set("value","")}},attachDatepicker:function(d,f,c){if(f!="copy"){return}var j=$(c).getProperty("rel").match(/datepicker\[[a-z0-9,]*\]/ig)[0].replace("datepicker[","").replace("]","").split(",");var k=$(c).getElement("tbody").getChildren();if(j.length>1||j[0]!=""){for(var g=0;g. + * + * PHP version 5 + * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 + * @package MultiColumnWizard + * @license http://opensource.org/licenses/lgpl-3.0.html + * @info tab is set to 4 whitespaces + */ + +var MultiColumnWizard = new Class( +{ + Implements: [Options], + options: + { + table: null, + maxCount: 0, + minCount: 0, + uniqueFields: [] + }, + + // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) + operationLoadCallbacks: [], + operationClickCallbacks: [], + operationUpdateCallbacks: [], + + /** + * Initialize the wizard + * @param Object options + */ + initialize: function(options) + { + this.setOptions(options); + + // make sure we really have the table as element + this.options.table = document.id(this.options.table); + + // Do not run this in the frontend, Backend class would not be available + if (window.Backend) + { + Backend.getScrollOffset(); + } + + var self = this; + + // execute load callback and register click event callback + this.options.table.getElement('tbody').getElements('tr').each(function(el, index) + { + el.getElement('td.operations').getElements('a').each(function(operation) + { + var key = operation.get('rel'); + + // call static load callbacks + if (MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // call instance load callbacks + if (self.operationLoadCallbacks[key]) + { + self.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + }); + }); + + this.updateOperations(); + }, + + + /** + * Update operations + */ + updateOperations: function() + { + var self = this; + + // execute load callback and register click event callback + this.options.table.getElement('tbody').getElements('tr').each(function(el, index) + { + el.getElement('td.operations').getElements('a').each(function(operation) + { + var key = operation.get('rel'); + + // remove all click events + operation.removeEvents('click'); + + // register static click callbacks + if (MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + }); + }); + } + + // register instance click callbacks + if (self.operationClickCallbacks[key]) + { + self.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + self.updateFields(index); + }); + }); + } + + //register updateOperations as last click event (see issue #40) + operation.addEvent('click', function(e) + { + e.preventDefault(); + self.updateOperations.pass([operation, el], self)(); + }); + + + // call static update callbacks + if (MultiColumnWizard.operationUpdateCallbacks[key]) + { + MultiColumnWizard.operationUpdateCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // call instance update callbacks + if (self.operationUpdateCallbacks[key]) + { + self.operationUpdateCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + + }); + }); + }, + + + /** + * Update row attributes + * @param int level + * @param element row + * @return element the updated element + */ + updateRowAttributes: function(level, row) + { + + row.getElements('.mcwUpdateFields *').each(function(el) + { + + /* + * We have to process the folowing steps: + * - delete elements created by choosen or other Scripst and create new ones if necessary + * - rewrite the attributes name, id, onlick, for + * - rewrite inline SCRIPT-tags + * + */ + + //remove choosen elements + if (el.hasClass('chzn-container')){ + el.destroy(); + return; + } + + // rewrite elements name + if (typeOf(el.getProperty('name')) == 'string') + { + var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); + if (erg) + { + + el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); + } + } + + // rewrite elements id or delete input fields without an id + if (typeOf(el.getProperty('id')) == 'string') + { + var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); + + } + } + + // rewrite elements onclick (e.g. pagePicker) + if (typeOf(el.getProperty('onclick')) == 'string') + { + var erg = el.getProperty('onclick').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + + el.setProperty('onclick', erg[1] + '_row' + level + '_' + erg[2]); + } + } + + //rewrite elements for attribute + if (typeOf(el.getProperty('for')) == 'string') + { + var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + + el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); + } + } + + // set attributes depending of the tag type + switch (el.nodeName.toUpperCase()) + { + + case 'SELECT': + //create new chosen (2.11 only) + if (el.hasClass('tl_chosen')) new Chosen(el); + break; + case 'INPUT': + //set input field to visible + if (el.getStyle('display').toLowerCase() == 'none') el.setStyle('display','inline'); + // delete input field without ids (these input fields are created by JS) + if (typeOf(el.getProperty('id')) != 'string') el.destroy(); + break; + case 'SCRIPT': + //rewrite inline + //ToDO: refactor this part. For some reason replace will only find the first token of _row[0-9]+_ + var newScript = ''; + var script = el.get('html').toString(); + var length = 0; + var start = script.search(/_row[0-9]+_/i); + while(start > 0) + { + length = script.match(/(_row[0-9]+)+_/i)[0].length; + newScript = newScript + script.substr(0, start) + '_row' + level + '_'; + script = script.substr(start + length); + start = script.search(/_row[0-9]+_/i); + } + + el.set('html', newScript+script); + + break; + } + + }); + + return row; + }, + + + /** + * Add a load callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!this.operationLoadCallbacks[key]) + { + this.operationLoadCallbacks[key] = []; + } + + this.operationLoadCallbacks[key].include(func); + }, + + /** + * Add a load callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationUpdateCallback: function(key, func) + { + if (!this.operationUpdateCallbacks[key]) + { + this.operationUpdateCallbacks[key] = []; + } + + this.operationLoadCallbacks[key].include(func); + }, + + + /** + * Add a click callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!this.operationClickCallbacks[key]) + { + this.operationClickCallbacks[key] = []; + } + + this.operationClickCallbacks[key].include(func); + } +}); + +/** + * Extend the MultiColumnWizard with some static functions + */ +Object.append(MultiColumnWizard, +{ + // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) + operationLoadCallbacks: {}, + operationClickCallbacks: {}, + operationUpdateCallbacks: {}, + + /** + * Add a load callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key] = []; + } + + MultiColumnWizard.operationLoadCallbacks[key].include(func); + }, + + /** + * Add a dupate callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationUpdateCallback: function(key, func) + { + if (!MultiColumnWizard.operationUpdateCallbacks[key]) + { + MultiColumnWizard.operationUpdateCallbacks[key] = []; + } + + MultiColumnWizard.operationUpdateCallbacks[key].include(func); + }, + + + /** + * Add a click callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key] = []; + } + + MultiColumnWizard.operationClickCallbacks[key].include(func); + }, + + + /** + * Operation "copy" - update + * @param Element the icon element + * @param Element the row + */ + copyUpdate: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // remove the copy possibility if we have already reached maxCount + if (this.options.maxCount > 0 && rowCount >= this.options.maxCount) + { + el.setStyle('display', 'none'); + }else{ + el.setStyle('display', 'inline'); + } + }, + + + /** + * Operation "copy" - click + * @param Element the icon element + * @param Element the row + */ + copyClick: function(el, row) + { + + var rowCount = row.getSiblings().length + 1; + + // check maxCount for an inject + if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) + { + + var copy = row.clone(true,true); + + //get the current level of the row + level = row.getAllPrevious().length; + + //update the row attributes + copy = this.updateRowAttributes(++level, copy); + copy.injectAfter(row); + + //exec script + if (copy.getElements('script').length > 0) + { + copy.getElements('script').each(function(script){ + $exec(script.get('html')); + }); + } + + //updtae the row attribute of the following rows + var that = this; + copy.getAllNext().each(function(row){ + that.updateRowAttributes(++level, row); + }); + } + }, + + + /** + * Operation "delete" - load + * @param Element the icon element + * @param Element the row + */ + deleteUpdate: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // remove the delete possibility if necessary + if (this.options.minCount > 0 && rowCount <= this.options.minCount) + { + el.setStyle('display', 'none'); + } + else + { + el.setStyle('display', 'inline'); + } + }, + + + /** + * Operation "delete" - click + * @param Element the icon element + * @param Element the row + */ + deleteClick: function(el, row) + { + //get all following rows + var rows = row.getAllNext(); + //extract the current level + level = row.getAllPrevious().length; + + //destroy current row + row.destroy(); + + var that = this; + //update index of following rows + rows.each(function(row){ + that.updateRowAttributes(level++, row); + }); + + //this.addOperationClickCallback('click', this.updateOperations); + this.updateOperations(); + + }, + + + /** + * Operation "up" - click + * @param Element the icon element + * @param Element the row + */ + upClick: function(el, row) + { + var previous = row.getPrevious(); + if (previous) + { + // update the attributes so the order remains as desired + // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! + var previousPosition = previous.getAllPrevious().length; + + // this is the dummy setting (guess no one will have more than 99999 entries ;-)) + previous = this.updateRowAttributes(99999, previous); + + // now set the correct values again + row = this.updateRowAttributes(previousPosition, row); + previous = this.updateRowAttributes(previousPosition+1, previous); + + row.injectBefore(previous); + } + }, + + + /** + * Operation "down" - click + * @param Element the icon element + * @param Element the row + */ + downClick: function(el, row) + { + var next = row.getNext(); + if (next) + { + // update the attributes so the order remains as desired + // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! + var rowPosition = row.getAllPrevious().length; + + // this is the dummy setting (guess no one will have more than 99999 entries ;-)) + row = this.updateRowAttributes(99999, row); + + // now set the correct values again + next = this.updateRowAttributes(rowPosition, next); + row = this.updateRowAttributes(rowPosition+1, row); + + row.injectAfter(next); + } + } +}); + + +/** + * Register default callbacks + */ +//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); +//MultiColumnWizard.addOperationClickCallback('copy', function(){alert('a'); }); +MultiColumnWizard.addOperationUpdateCallback('copy', MultiColumnWizard.copyUpdate); +MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); +MultiColumnWizard.addOperationUpdateCallback('delete', MultiColumnWizard.deleteUpdate); +MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); +MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); + diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js new file mode 100644 index 0000000..1dc3863 --- /dev/null +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js @@ -0,0 +1,389 @@ +/** + * Contao Open Source CMS + * Copyright (C) 2005-2011 Leo Feyer + * + * Formerly known as TYPOlight Open Source CMS. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, please visit the Free + * Software Foundation website at . + * + * PHP version 5 + * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 + * @package MultiColumnWizard + * @license http://opensource.org/licenses/lgpl-3.0.html + * @info tab is set to 4 whitespaces + */ + +var MultiColumnWizard = new Class( +{ + Implements: [Options], + options: + { + table: null, + maxCount: 0, + minCount: 0, + uniqueFields: [] + }, + + // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) + operationLoadCallbacks: [], + operationClickCallbacks: [], + + /** + * Initialize the wizard + * @param Object options + */ + initialize: function(options) + { + this.setOptions(options); + + // make sure we really have the table as element + this.options.table = document.id(this.options.table); + + // Do not run this in the frontend, Backend class would not be available + if (window.Backend) + { + Backend.getScrollOffset(); + } + + this.updateOperations(); + }, + + + /** + * Update operations + */ + updateOperations: function() + { + var self = this; + + // execute load callback and register click event callback + this.options.table.getElement('tbody').getElements('tr').each(function(el, index) + { + el.getElement('td.operations').getElements('a').each(function(operation) + { + var key = operation.get('rel'); + + // register static load callbacks + if (MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // register instance load callbacks + if (self.operationLoadCallbacks[key]) + { + self.operationLoadCallbacks[key].each(function(callback) + { + callback.pass([operation, el], self)(); + }); + } + + // remove all click events + operation.removeEvents('click'); + + // register static click callbacks + if (MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + }); + }); + } + + // register instance click callbacks + if (self.operationClickCallbacks[key]) + { + self.operationClickCallbacks[key].each(function(callback) + { + operation.addEvent('click', function(e) + { + e.preventDefault(); + callback.pass([operation, el], self)(); + self.updateFields(index); + }); + }); + } + }); + }); + }, + + + /** + * Update row attributes + * @param int level + * @param element row + * @return element the updated element + */ + updateRowAttributes: function(level, row) + { + row.getElements('.mcwUpdateFields *[name]').each(function(el) + { + // rewrite elements name + if (typeOf(el.getProperty('name')) == 'string') + { + var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); + if (erg) + { + el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); + } + } + + // rewrite elements id + if (typeOf(el.getProperty('id')) == 'string') + { + var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); + } + } + }); + + row.getElements('.mcwUpdateFields label').each(function(el) + { + // rewrite elements for + if (typeOf(el.getProperty('for')) == 'string') + { + var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); + if (erg) + { + el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); + } + } + }); + + return row; + }, + + + /** + * Add a load callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!this.operationLoadCallbacks[key]) + { + this.operationLoadCallbacks[key] = []; + } + + this.operationLoadCallbacks[key].include(func); + }, + + + /** + * Add a click callback for the instance + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!this.operationClickCallbacks[key]) + { + this.operationClickCallbacks[key] = []; + } + + this.operationClickCallbacks[key].include(func); + } +}); + +/** + * Extend the MultiColumnWizard with some static functions + */ +Object.append(MultiColumnWizard, +{ + // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) + operationLoadCallbacks: {}, + operationClickCallbacks: {}, + + /** + * Add a load callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationLoadCallback: function(key, func) + { + if (!MultiColumnWizard.operationLoadCallbacks[key]) + { + MultiColumnWizard.operationLoadCallbacks[key] = []; + } + + MultiColumnWizard.operationLoadCallbacks[key].include(func); + }, + + + /** + * Add a click callback for all the MCW's + * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) + * @param function callback + */ + addOperationClickCallback: function(key, func) + { + if (!MultiColumnWizard.operationClickCallbacks[key]) + { + MultiColumnWizard.operationClickCallbacks[key] = []; + } + + MultiColumnWizard.operationClickCallbacks[key].include(func); + }, + + + /** + * Operation "copy" - load + * @param Element the icon element + * @param Element the row + */ + copyLoad: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // remove the copy possibility if we have already reached maxCount + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "copy" - click + * @param Element the icon element + * @param Element the row + */ + copyClick: function(el, row) + { + var rowCount = row.getSiblings().length + 1; + + // check maxCount for an inject + if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) + { + // update the row count + ++rowCount; + + var copy = row.clone(true,true); + + copy = this.updateRowAttributes(rowCount-1, copy); + copy.injectAfter(row); + + this.addOperationClickCallback('click', this.updateOperations); + } + + // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) + if (this.options.maxCount > 0 && rowCount == this.options.maxCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - load + * @param Element the icon element + * @param Element the row + */ + deleteLoad: function(el, row) + { + var position = el.getAllPrevious().length - 1; + + // remove the delete possibility if necessary + if (this.options.minCount > 0 && position == this.options.minCount) + { + el.destroy(); + } + }, + + + /** + * Operation "delete" - click + * @param Element the icon element + * @param Element the row + */ + deleteClick: function(el, row) + { + row.destroy(); + }, + + + /** + * Operation "up" - click + * @param Element the icon element + * @param Element the row + */ + upClick: function(el, row) + { + var previous = row.getPrevious(); + if (previous) + { + // update the attributes so the order remains as desired + // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! + var previousPosition = previous.getAllPrevious().length; + + // this is the dummy setting (guess no one will have more than 99999 entries ;-)) + previous = this.updateRowAttributes(99999, previous); + + // now set the correct values again + row = this.updateRowAttributes(previousPosition, row); + previous = this.updateRowAttributes(previousPosition+1, previous); + + row.injectBefore(previous); + } + }, + + + /** + * Operation "down" - click + * @param Element the icon element + * @param Element the row + */ + downClick: function(el, row) + { + var next = row.getNext(); + if (next) + { + // update the attributes so the order remains as desired + // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! + var rowPosition = row.getAllPrevious().length; + + // this is the dummy setting (guess no one will have more than 99999 entries ;-)) + row = this.updateRowAttributes(99999, row); + + // now set the correct values again + next = this.updateRowAttributes(rowPosition, next); + row = this.updateRowAttributes(rowPosition+1, row); + + row.injectAfter(next); + } + } +}); + + +/** + * Register default callbacks + */ +//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); +MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.copyLoad); +MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); +MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); +MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); +MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js deleted file mode 100644 index 7c0503d..0000000 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js +++ /dev/null @@ -1,460 +0,0 @@ -/** - * Contao Open Source CMS - * Copyright (C) 2005-2011 Leo Feyer - * - * Formerly known as TYPOlight Open Source CMS. - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program. If not, please visit the Free - * Software Foundation website at . - * - * PHP version 5 - * @copyright Andreas Schempp 2011, certo web & design GmbH 2011, MEN AT WORK 2011 - * @package MultiColumnWizard - * @license http://opensource.org/licenses/lgpl-3.0.html - */ - -var MultiColumnWizard = new Class( -{ - Implements: [Options], - options: - { - table: null, - maxCount: 0, - minCount: 0, - uniqueFields: [] - }, - - // instance callbacks (use e.g. myMCWVar.addOperationCallback() to register a callback that is for ONE specific MCW only) - operationLoadCallbacks: [], - operationClickCallbacks: [], - - /** - * Initialize the wizard - * @param Object options - */ - initialize: function(options) - { - this.setOptions(options); - - // make sure we really have the table as element - this.options.table = document.id(this.options.table); - - // Do not run this in the frontend, Backend class would not be available - if (window.Backend) - { - Backend.getScrollOffset(); - } - - this.updateOperations(); - }, - - - /** - * Update operations - */ - updateOperations: function() - { - var self = this; - - // execute load callback and register click event callback - this.options.table.getElement('tbody').getElements('tr').each(function(el, index) - { - el.getElement('td.operations').getElements('a').each(function(operation) - { - var key = operation.get('rel'); - - // register static load callbacks - if (MultiColumnWizard.operationLoadCallbacks[key]) - { - MultiColumnWizard.operationLoadCallbacks[key].each(function(callback) - { - callback.pass([operation, el], self)(); - }); - } - - // register instance load callbacks - if (self.operationLoadCallbacks[key]) - { - self.operationLoadCallbacks[key].each(function(callback) - { - callback.pass([operation, el], self)(); - }); - } - - // remove all click events - operation.removeEvents('click'); - - // register static click callbacks - if (MultiColumnWizard.operationClickCallbacks[key]) - { - MultiColumnWizard.operationClickCallbacks[key].each(function(callback) - { - operation.addEvent('click', function(e) - { - e.preventDefault(); - callback.pass([operation, el], self)(); - }); - }); - } - - // register instance click callbacks - if (self.operationClickCallbacks[key]) - { - self.operationClickCallbacks[key].each(function(callback) - { - operation.addEvent('click', function(e) - { - e.preventDefault(); - callback.pass([operation, el], self)(); - self.updateFields(index); - }); - }); - } - }); - }); - }, - - - /** - * Update row attributes - * @param int level - * @param element row - * @return element the updated element - */ - updateRowAttributes: function(level, row) - { - - row.getElements('.mcwUpdateFields *').each(function(el) - { - // rewrite elements name - if (typeOf(el.getProperty('name')) == 'string') - { - var erg = el.getProperty('name').match(/^([^\[]+)\[([0-9]+)\](.*)$/i); - if (erg) - { - - el.setProperty('name', erg[1] + '[' + level + ']' + erg[3]); - } - } - - // rewrite elements id - if (typeOf(el.getProperty('id')) == 'string') - { - - var erg = el.getProperty('id').match(/^(.+)_row[0-9]+_(.+)$/i); - if (erg) - { - el.setProperty('id', erg[1] + '_row' + level + '_' + erg[2]); - - //make input field visible again, if some js made set display:none - if (el.nodeName == 'INPUT' && el.getProperty('style').search('none;') > 0) el.setProperty('style','display: inline;'); - } - } - else - { - //eliminate input fields without an id -> this iput field was created by JS (i hope so :)) - if (el.nodeName == 'INPUT') el.destroy(); - } - - // rewrite elements onclick (e.g. pagePicker) - if (typeOf(el.getProperty('onclick')) == 'string') - { - var erg = el.getProperty('onclick').match(/^(.+)_row[0-9]+_(.+)$/i); - if (erg) - { - - el.setProperty('onclick', erg[1] + '_row' + level + '_' + erg[2]); - } - } - }); - - row.getElements('.mcwUpdateFields label').each(function(el) - { - // rewrite elements for - if (typeOf(el.getProperty('for')) == 'string') - { - var erg = el.getProperty('for').match(/^(.+)_row[0-9]+_(.+)$/i); - if (erg) - { - - el.setProperty('for', erg[1] + '_row' + level + '_' + erg[2]); - } - } - }); - - // modify inline scripts - row.getElements('.mcwUpdateFields script').each(function(el) - { - //ToDO: refactor this part. For some reason replace will only find the first token of _row[0-9]+_ - var newScript = ''; - var script = el.get('html').toString(); - var length = 0; - var start = script.search(/_row[0-9]+_/i); - while(start > 0) - { - - length = script.match(/(_row[0-9]+)+_/i)[0].length; - newScript = newScript + script.substr(0, start) + '_row' + level + '_'; - script = script.substr(start + length); - start = script.search(/_row[0-9]+_/i); - } - - el.set('html', newScript+script); - - }); - - return row; - }, - - - /** - * Add a load callback for the instance - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationLoadCallback: function(key, func) - { - if (!this.operationLoadCallbacks[key]) - { - this.operationLoadCallbacks[key] = []; - } - - this.operationLoadCallbacks[key].include(func); - }, - - - /** - * Add a click callback for the instance - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationClickCallback: function(key, func) - { - if (!this.operationClickCallbacks[key]) - { - this.operationClickCallbacks[key] = []; - } - - this.operationClickCallbacks[key].include(func); - } -}); - -/** - * Extend the MultiColumnWizard with some static functions - */ -Object.append(MultiColumnWizard, -{ - // static callbacks (use e.g. MultiColumnWizard.addOperationCallback() to register a callback that is for EVERY MCW on the page) - operationLoadCallbacks: {}, - operationClickCallbacks: {}, - - /** - * Add a load callback for all the MCW's - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationLoadCallback: function(key, func) - { - if (!MultiColumnWizard.operationLoadCallbacks[key]) - { - MultiColumnWizard.operationLoadCallbacks[key] = []; - } - - MultiColumnWizard.operationLoadCallbacks[key].include(func); - }, - - - /** - * Add a click callback for all the MCW's - * @param string the key e.g. 'copy' - your button has to have the matching rel="" attribute (...) - * @param function callback - */ - addOperationClickCallback: function(key, func) - { - if (!MultiColumnWizard.operationClickCallbacks[key]) - { - MultiColumnWizard.operationClickCallbacks[key] = []; - } - - MultiColumnWizard.operationClickCallbacks[key].include(func); - }, - - - /** - * Operation "copy" - load - * @param Element the icon element - * @param Element the row - */ - copyLoad: function(el, row) - { - var rowCount = row.getSiblings().length + 1; - - // remove the copy possibility if we have already reached maxCount - if (this.options.maxCount > 0 && rowCount >= this.options.maxCount) - { - el.setStyle('display', 'none'); - }else{ - el.setStyle('display', 'inline'); - } - }, - - - /** - * Operation "copy" - click - * @param Element the icon element - * @param Element the row - */ - copyClick: function(el, row) - { - - var rowCount = row.getSiblings().length + 1; - - // check maxCount for an inject - if (this.options.maxCount == 0 || (this.options.maxCount > 0 && rowCount < this.options.maxCount)) - { - // update the row count - ++rowCount; - - var copy = row.clone(true,true); - - copy = this.updateRowAttributes(rowCount-1, copy); - copy.injectAfter(row); - //exec script - if (copy.getElements('script').length > 0) - { - copy.getElements('script').each(function(script){ - $exec(script.get('html')); - }); - } - this.addOperationClickCallback('click', this.updateOperations()); - } - - // remove the copy possibility if we just reach maxCount now (don't need to increment rowCount here as we already did when injecting) - if (this.options.maxCount > 0 && rowCount == this.options.maxCount) - { - row.getSiblings().getElements('a[rel="copy"]').each(function(e){e.setStyle('display', 'none')}); - el.setStyle('display', 'none'); - } - }, - - - /** - * Operation "delete" - load - * @param Element the icon element - * @param Element the row - */ - deleteLoad: function(el, row) - { - var rowCount = row.getSiblings().length + 1; - - // remove the delete possibility if necessary - if (this.options.minCount > 0 && rowCount <= this.options.minCount) - { - el.setStyle('display', 'none'); - } - else - { - el.setStyle('display', 'inline'); - } - }, - - - /** - * Operation "delete" - click - * @param Element the icon element - * @param Element the row - */ - deleteClick: function(el, row) - { - //get all following rows - var rows = row.getAllNext(); - //extract the current level - level = row.getElements('.mcwUpdateFields *[name]')[0].getProperty('id').match(/_row[0-9]+_/i)[0].match(/[0-9]+/i)[0]; - //destroy current row - row.destroy(); - - var that = this; - //update index of following rows - rows.each(function(row){ - that.updateRowAttributes(level++, row); - }); - - this.addOperationClickCallback('click', this.updateOperations()); - - }, - - - /** - * Operation "up" - click - * @param Element the icon element - * @param Element the row - */ - upClick: function(el, row) - { - var previous = row.getPrevious(); - if (previous) - { - // update the attributes so the order remains as desired - // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! - var previousPosition = previous.getAllPrevious().length; - - // this is the dummy setting (guess no one will have more than 99999 entries ;-)) - previous = this.updateRowAttributes(99999, previous); - - // now set the correct values again - row = this.updateRowAttributes(previousPosition, row); - previous = this.updateRowAttributes(previousPosition+1, previous); - - row.injectBefore(previous); - } - }, - - - /** - * Operation "down" - click - * @param Element the icon element - * @param Element the row - */ - downClick: function(el, row) - { - var next = row.getNext(); - if (next) - { - // update the attributes so the order remains as desired - // we have to set it to a value that is not in the DOM first, otherwise the values will get lost!! - var rowPosition = row.getAllPrevious().length; - - // this is the dummy setting (guess no one will have more than 99999 entries ;-)) - row = this.updateRowAttributes(99999, row); - - // now set the correct values again - next = this.updateRowAttributes(rowPosition, next); - row = this.updateRowAttributes(rowPosition+1, row); - - row.injectAfter(next); - } - } -}); - - -/** - * Register default callbacks - */ -//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); -MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.copyLoad); -MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); -MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); -MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); -MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); -MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); From e838b6c8e80f9078d5ef51bcb161ff6b99c27fe3 Mon Sep 17 00:00:00 2001 From: David Maack Date: Tue, 24 Apr 2012 10:33:37 +0200 Subject: [PATCH 16/21] Added YACE support - this feature will only be supported until the requester of this feature gets rude on IRC :) --- system/modules/multicolumnwizard/MultiColumnWizard.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index a8f384d..cf92bf6 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -609,7 +609,11 @@ protected function getMcWDatePickerString($strId, $strKey, $rgxp) protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) { $xlabel = ''; - + $strContaoPrefix = 'contao/'; + + // YACE support for leo unglaub :) + if (defined(YACE)) $strContaoPrefix = ''; + // Toggle line wrap (textarea) if ($arrField['inputType'] == 'textarea' && $arrField['eval']['rte'] == '') { @@ -619,7 +623,7 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) // Add the help wizard if ($arrField['eval']['helpwizard']) { - $xlabel .= ' ' . $this->generateImage('about.gif', $GLOBALS['TL_LANG']['MSC']['helpWizard'], 'style="vertical-align:text-bottom;"') . ''; + $xlabel .= ' ' . $this->generateImage('about.gif', $GLOBALS['TL_LANG']['MSC']['helpWizard'], 'style="vertical-align:text-bottom;"') . ''; } // Add the popup file manager @@ -632,7 +636,7 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) $path = '?node=' . $arrField['eval']['path']; } - $xlabel .= ' ' . $this->generateImage('filemanager.gif', $GLOBALS['TL_LANG']['MSC']['fileManager'], 'style="vertical-align:text-bottom;"') . ''; + $xlabel .= ' ' . $this->generateImage('filemanager.gif', $GLOBALS['TL_LANG']['MSC']['fileManager'], 'style="vertical-align:text-bottom;"') . ''; } // Add the table import wizard From fb59e5adcc038e92da488342496c7cc7c286286e Mon Sep 17 00:00:00 2001 From: David Maack Date: Tue, 24 Apr 2012 12:48:01 +0200 Subject: [PATCH 17/21] Bugfix, thanks to Tristan Lins see: https://github.com/menatwork/MultiColumnWizard/commit/e838b6c8e80f9078d5ef51bcb161ff6b99c27fe3#commitcomment-1249385 --- system/modules/multicolumnwizard/MultiColumnWizard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index cf92bf6..cd69d6e 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -612,7 +612,7 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) $strContaoPrefix = 'contao/'; // YACE support for leo unglaub :) - if (defined(YACE)) $strContaoPrefix = ''; + if (defined('YACE')) $strContaoPrefix = ''; // Toggle line wrap (textarea) if ($arrField['inputType'] == 'textarea' && $arrField['eval']['rte'] == '') From ddc2742233e8fb821332340955465890d2c746f8 Mon Sep 17 00:00:00 2001 From: David Maack Date: Mon, 30 Apr 2012 09:33:08 +0200 Subject: [PATCH 18/21] Added $this->activeRow while walking the columns of the MCW. See Issue #48 --- system/modules/multicolumnwizard/LICENSE.txt | 2 +- system/modules/multicolumnwizard/MultiColumnWizard.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/system/modules/multicolumnwizard/LICENSE.txt b/system/modules/multicolumnwizard/LICENSE.txt index 6d58784..62323ce 100644 --- a/system/modules/multicolumnwizard/LICENSE.txt +++ b/system/modules/multicolumnwizard/LICENSE.txt @@ -18,4 +18,4 @@ * Author Andreas Schempp * Link http://www.iserv.ch/ * License GNU/LGPL - */ \ No newline at end of file + */ \ No newline at end of file diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index cd69d6e..92b1324 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -204,6 +204,8 @@ protected function validator($varInput) { for ($i = 0; $i < count($varInput); $i++) { + $this->activeRow = $i; + // Walk every column foreach ($this->columnFields as $strKey => $arrField) { @@ -384,6 +386,7 @@ public function generate() // Add input fields for ($i = 0; $i < $intNumberOfRows; $i++) { + $this->activeRow = $i; $strHidden = ''; // Walk every column From a2efecc07fd53a494a0e50b560d0052d46c16c0c Mon Sep 17 00:00:00 2001 From: David Maack Date: Mon, 30 Apr 2012 09:54:39 +0200 Subject: [PATCH 19/21] fixed issue #49 --- .../html/js/multicolumnwizard_be_src.js | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js index 7fcfae9..a79cf25 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js @@ -468,23 +468,30 @@ Object.append(MultiColumnWizard, */ deleteClick: function(el, row) { - //get all following rows - var rows = row.getAllNext(); - //extract the current level - level = row.getAllPrevious().length; - - //destroy current row - row.destroy(); - var that = this; - //update index of following rows - rows.each(function(row){ - that.updateRowAttributes(level++, row); - }); - - //this.addOperationClickCallback('click', this.updateOperations); - this.updateOperations(); + if (row.getSiblings().length > 0){ + //get all following rows + var rows = row.getAllNext(); + //extract the current level + level = row.getAllPrevious().length; + + //destroy current row + row.destroy(); + + var that = this; + //update index of following rows + rows.each(function(row){ + + that.updateRowAttributes(level++, row); + + }); + }else{ + row.getElements('input,select,textarea').each(function(el){ + MultiColumnWizard.clearElementValue(el); + + }); + } }, @@ -515,10 +522,10 @@ Object.append(MultiColumnWizard, /** - * Operation "down" - click - * @param Element the icon element - * @param Element the row - */ + * Operation "down" - click + * @param Element the icon element + * @param Element the row + */ downClick: function(el, row) { var next = row.getNext(); @@ -537,15 +544,28 @@ Object.append(MultiColumnWizard, row.injectAfter(next); } - } + }, + + /** + * @param Element the element which should be cleared + */ + clearElementValue: function(el) + { + if (el.get('type') == 'checkbox' || el.get('type') == 'radio') + { + el.checked = false; + } + else + { + el.set('value', ''); + } + } }); /** * Register default callbacks */ -//MultiColumnWizard.addOperationLoadCallback('copy', MultiColumnWizard.attachDatepicker); -//MultiColumnWizard.addOperationClickCallback('copy', function(){alert('a'); }); MultiColumnWizard.addOperationUpdateCallback('copy', MultiColumnWizard.copyUpdate); MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick); MultiColumnWizard.addOperationUpdateCallback('delete', MultiColumnWizard.deleteUpdate); From e8153d70584b7fd8c3d8bc9a8129766fc168377f Mon Sep 17 00:00:00 2001 From: David Maack Date: Mon, 30 Apr 2012 10:47:21 +0200 Subject: [PATCH 20/21] Add and linked minified files --- system/modules/multicolumnwizard/MultiColumnWizard.php | 6 ++---- system/modules/multicolumnwizard/config/config.php | 2 +- .../multicolumnwizard/html/js/multicolumnwizard_be.js | 1 + .../multicolumnwizard/html/js/multicolumnwizard_be_src.js | 3 +-- .../multicolumnwizard/html/js/multicolumnwizard_fe.js | 1 + .../multicolumnwizard/html/js/multicolumnwizard_fe_src.js | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js create mode 100644 system/modules/multicolumnwizard/html/js/multicolumnwizard_fe.js diff --git a/system/modules/multicolumnwizard/MultiColumnWizard.php b/system/modules/multicolumnwizard/MultiColumnWizard.php index 92b1324..3944678 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -1,5 +1,4 @@ -columnFields = $this->{$this->arrCallback[0]}->{$this->arrCallback[1]}($this); } - // TODO: minify this and change path - $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_' . strtolower(TL_MODE) . '_src.js'; + $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_' . strtolower(TL_MODE) . '.js'; $GLOBALS['TL_CSS'][] = 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; $this->strCommand = 'cmd_' . $this->strField; diff --git a/system/modules/multicolumnwizard/config/config.php b/system/modules/multicolumnwizard/config/config.php index 3aa24be..f8e7158 100644 --- a/system/modules/multicolumnwizard/config/config.php +++ b/system/modules/multicolumnwizard/config/config.php @@ -21,7 +21,7 @@ * Software Foundation website at . * * PHP version 5 - * @copyright MEN AT WORK 2011, certo web & design GmbH 2011 + * @copyright MEN AT WORK 2012, certo web & design GmbH 2012 * @package MultiColumnWizard * @license LGPL * @filesource diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js new file mode 100644 index 0000000..3bd1308 --- /dev/null +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js @@ -0,0 +1 @@ +var MultiColumnWizard=new Class({Implements:[Options],options:{table:null,maxCount:0,minCount:0,uniqueFields:[]},operationLoadCallbacks:[],operationClickCallbacks:[],operationUpdateCallbacks:[],initialize:function(b){this.setOptions(b);this.options.table=document.id(this.options.table);if(window.Backend){Backend.getScrollOffset()}var a=this;this.options.table.getElement("tbody").getElements("tr").each(function(d,c){d.getElement("td.operations").getElements("a").each(function(e){var f=e.get("rel");if(MultiColumnWizard.operationLoadCallbacks[f]){MultiColumnWizard.operationLoadCallbacks[f].each(function(g){g.pass([e,d],a)()})}if(a.operationLoadCallbacks[f]){a.operationLoadCallbacks[f].each(function(g){g.pass([e,d],a)()})}})});this.updateOperations()},updateOperations:function(){var a=this;this.options.table.getElement("tbody").getElements("tr").each(function(c,b){c.getElement("td.operations").getElements("a").each(function(d){var e=d.get("rel");d.removeEvents("click");if(MultiColumnWizard.operationClickCallbacks[e]){MultiColumnWizard.operationClickCallbacks[e].each(function(f){d.addEvent("click",function(g){g.preventDefault();f.pass([d,c],a)()})})}if(a.operationClickCallbacks[e]){a.operationClickCallbacks[e].each(function(f){d.addEvent("click",function(g){g.preventDefault();f.pass([d,c],a)();a.updateFields(b)})})}d.addEvent("click",function(f){f.preventDefault();a.updateOperations.pass([d,c],a)()});if(MultiColumnWizard.operationUpdateCallbacks[e]){MultiColumnWizard.operationUpdateCallbacks[e].each(function(f){f.pass([d,c],a)()})}if(a.operationUpdateCallbacks[e]){a.operationUpdateCallbacks[e].each(function(f){f.pass([d,c],a)()})}})})},updateRowAttributes:function(b,a){a.getElements(".mcwUpdateFields *").each(function(e){if(e.hasClass("chzn-container")){e.destroy();return}if(typeOf(e.getProperty("name"))=="string"){var g=e.getProperty("name").match(/^([^\[]+)\[([0-9]+)\](.*)$/i);if(g){e.setProperty("name",g[1]+"["+b+"]"+g[3])}}if(typeOf(e.getProperty("id"))=="string"){var g=e.getProperty("id").match(/^(.+)_row[0-9]+_(.+)$/i);if(g){e.setProperty("id",g[1]+"_row"+b+"_"+g[2])}}if(typeOf(e.getProperty("onclick"))=="string"){var g=e.getProperty("onclick").match(/^(.+)_row[0-9]+_(.+)$/i);if(g){e.setProperty("onclick",g[1]+"_row"+b+"_"+g[2])}}if(typeOf(e.getProperty("for"))=="string"){var g=e.getProperty("for").match(/^(.+)_row[0-9]+_(.+)$/i);if(g){e.setProperty("for",g[1]+"_row"+b+"_"+g[2])}}switch(e.nodeName.toUpperCase()){case"SELECT":if(e.hasClass("tl_chosen")){new Chosen(e)}break;case"INPUT":if(e.getStyle("display").toLowerCase()=="none"){e.setStyle("display","inline")}if(typeOf(e.getProperty("id"))!="string"){e.destroy()}break;case"SCRIPT":var d="";var c=e.get("html").toString();var f=0;var h=c.search(/_row[0-9]+_/i);while(h>0){f=c.match(/(_row[0-9]+)+_/i)[0].length;d=d+c.substr(0,h)+"_row"+b+"_";c=c.substr(h+f);h=c.search(/_row[0-9]+_/i)}e.set("html",d+c);break}});return a},addOperationLoadCallback:function(a,b){if(!this.operationLoadCallbacks[a]){this.operationLoadCallbacks[a]=[]}this.operationLoadCallbacks[a].include(b)},addOperationUpdateCallback:function(a,b){if(!this.operationUpdateCallbacks[a]){this.operationUpdateCallbacks[a]=[]}this.operationLoadCallbacks[a].include(b)},addOperationClickCallback:function(a,b){if(!this.operationClickCallbacks[a]){this.operationClickCallbacks[a]=[]}this.operationClickCallbacks[a].include(b)}});Object.append(MultiColumnWizard,{operationLoadCallbacks:{},operationClickCallbacks:{},operationUpdateCallbacks:{},addOperationLoadCallback:function(a,b){if(!MultiColumnWizard.operationLoadCallbacks[a]){MultiColumnWizard.operationLoadCallbacks[a]=[]}MultiColumnWizard.operationLoadCallbacks[a].include(b)},addOperationUpdateCallback:function(a,b){if(!MultiColumnWizard.operationUpdateCallbacks[a]){MultiColumnWizard.operationUpdateCallbacks[a]=[]}MultiColumnWizard.operationUpdateCallbacks[a].include(b)},addOperationClickCallback:function(a,b){if(!MultiColumnWizard.operationClickCallbacks[a]){MultiColumnWizard.operationClickCallbacks[a]=[]}MultiColumnWizard.operationClickCallbacks[a].include(b)},copyUpdate:function(b,c){var a=c.getSiblings().length+1;if(this.options.maxCount>0&&a>=this.options.maxCount){b.setStyle("display","none")}else{b.setStyle("display","inline")}},copyClick:function(b,d){var a=d.getSiblings().length+1;if(this.options.maxCount==0||(this.options.maxCount>0&&a0){e.getElements("script").each(function(f){$exec(f.get("html"))})}var c=this;e.getAllNext().each(function(f){c.updateRowAttributes(++level,f)})}},deleteUpdate:function(b,c){var a=c.getSiblings().length+1;if(this.options.minCount>0&&a<=this.options.minCount){b.setStyle("display","none")}else{b.setStyle("display","inline")}},deleteClick:function(a,d){if(d.getSiblings().length>0){var c=d.getAllNext();level=d.getAllPrevious().length;d.destroy();var b=this;c.each(function(e){b.updateRowAttributes(level++,e)})}else{d.getElements("input,select,textarea").each(function(e){MultiColumnWizard.clearElementValue(e)})}},upClick:function(b,d){var c=d.getPrevious();if(c){var a=c.getAllPrevious().length;c=this.updateRowAttributes(99999,c);d=this.updateRowAttributes(a,d);c=this.updateRowAttributes(a+1,c);d.injectBefore(c)}},downClick:function(c,d){var b=d.getNext();if(b){var a=d.getAllPrevious().length;d=this.updateRowAttributes(99999,d);b=this.updateRowAttributes(a,b);d=this.updateRowAttributes(a+1,d);d.injectAfter(b)}},clearElementValue:function(a){if(a.get("type")=="checkbox"||a.get("type")=="radio"){a.checked=false}else{a.set("value","")}}});MultiColumnWizard.addOperationUpdateCallback("copy",MultiColumnWizard.copyUpdate);MultiColumnWizard.addOperationClickCallback("copy",MultiColumnWizard.copyClick);MultiColumnWizard.addOperationUpdateCallback("delete",MultiColumnWizard.deleteUpdate);MultiColumnWizard.addOperationClickCallback("delete",MultiColumnWizard.deleteClick);MultiColumnWizard.addOperationClickCallback("up",MultiColumnWizard.upClick);MultiColumnWizard.addOperationClickCallback("down",MultiColumnWizard.downClick); \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js index a79cf25..6f43b03 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js @@ -571,5 +571,4 @@ MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick) MultiColumnWizard.addOperationUpdateCallback('delete', MultiColumnWizard.deleteUpdate); MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); -MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); - +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe.js new file mode 100644 index 0000000..d32a0fe --- /dev/null +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe.js @@ -0,0 +1 @@ +var MultiColumnWizard=new Class({Implements:[Options],options:{table:null,maxCount:0,minCount:0,uniqueFields:[]},operationLoadCallbacks:[],operationClickCallbacks:[],initialize:function(a){this.setOptions(a);this.options.table=document.id(this.options.table);if(window.Backend){Backend.getScrollOffset()}this.updateOperations()},updateOperations:function(){var a=this;this.options.table.getElement("tbody").getElements("tr").each(function(c,b){c.getElement("td.operations").getElements("a").each(function(d){var e=d.get("rel");if(MultiColumnWizard.operationLoadCallbacks[e]){MultiColumnWizard.operationLoadCallbacks[e].each(function(f){f.pass([d,c],a)()})}if(a.operationLoadCallbacks[e]){a.operationLoadCallbacks[e].each(function(f){f.pass([d,c],a)()})}d.removeEvents("click");if(MultiColumnWizard.operationClickCallbacks[e]){MultiColumnWizard.operationClickCallbacks[e].each(function(f){d.addEvent("click",function(g){g.preventDefault();f.pass([d,c],a)()})})}if(a.operationClickCallbacks[e]){a.operationClickCallbacks[e].each(function(f){d.addEvent("click",function(g){g.preventDefault();f.pass([d,c],a)();a.updateFields(b)})})}})})},updateRowAttributes:function(b,a){a.getElements(".mcwUpdateFields *[name]").each(function(c){if(typeOf(c.getProperty("name"))=="string"){var d=c.getProperty("name").match(/^([^\[]+)\[([0-9]+)\](.*)$/i);if(d){c.setProperty("name",d[1]+"["+b+"]"+d[3])}}if(typeOf(c.getProperty("id"))=="string"){var d=c.getProperty("id").match(/^(.+)_row[0-9]+_(.+)$/i);if(d){c.setProperty("id",d[1]+"_row"+b+"_"+d[2])}}});a.getElements(".mcwUpdateFields label").each(function(c){if(typeOf(c.getProperty("for"))=="string"){var d=c.getProperty("for").match(/^(.+)_row[0-9]+_(.+)$/i);if(d){c.setProperty("for",d[1]+"_row"+b+"_"+d[2])}}});return a},addOperationLoadCallback:function(a,b){if(!this.operationLoadCallbacks[a]){this.operationLoadCallbacks[a]=[]}this.operationLoadCallbacks[a].include(b)},addOperationClickCallback:function(a,b){if(!this.operationClickCallbacks[a]){this.operationClickCallbacks[a]=[]}this.operationClickCallbacks[a].include(b)}});Object.append(MultiColumnWizard,{operationLoadCallbacks:{},operationClickCallbacks:{},addOperationLoadCallback:function(a,b){if(!MultiColumnWizard.operationLoadCallbacks[a]){MultiColumnWizard.operationLoadCallbacks[a]=[]}MultiColumnWizard.operationLoadCallbacks[a].include(b)},addOperationClickCallback:function(a,b){if(!MultiColumnWizard.operationClickCallbacks[a]){MultiColumnWizard.operationClickCallbacks[a]=[]}MultiColumnWizard.operationClickCallbacks[a].include(b)},copyLoad:function(b,c){var a=c.getSiblings().length+1;if(this.options.maxCount>0&&a==this.options.maxCount){b.destroy()}},copyClick:function(b,c){var a=c.getSiblings().length+1;if(this.options.maxCount==0||(this.options.maxCount>0&&a0&&a==this.options.maxCount){b.destroy()}},deleteLoad:function(b,c){var a=b.getAllPrevious().length-1;if(this.options.minCount>0&&a==this.options.minCount){b.destroy()}},deleteClick:function(a,b){b.destroy()},upClick:function(b,d){var c=d.getPrevious();if(c){var a=c.getAllPrevious().length;c=this.updateRowAttributes(99999,c);d=this.updateRowAttributes(a,d);c=this.updateRowAttributes(a+1,c);d.injectBefore(c)}},downClick:function(c,d){var b=d.getNext();if(b){var a=d.getAllPrevious().length;d=this.updateRowAttributes(99999,d);b=this.updateRowAttributes(a,b);d=this.updateRowAttributes(a+1,d);d.injectAfter(b)}}});MultiColumnWizard.addOperationLoadCallback("copy",MultiColumnWizard.copyLoad);MultiColumnWizard.addOperationClickCallback("copy",MultiColumnWizard.copyClick);MultiColumnWizard.addOperationLoadCallback("delete",MultiColumnWizard.deleteLoad);MultiColumnWizard.addOperationClickCallback("delete",MultiColumnWizard.deleteClick);MultiColumnWizard.addOperationClickCallback("up",MultiColumnWizard.upClick);MultiColumnWizard.addOperationClickCallback("down",MultiColumnWizard.downClick); \ No newline at end of file diff --git a/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js index 1dc3863..165e986 100644 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_fe_src.js @@ -386,4 +386,4 @@ MultiColumnWizard.addOperationClickCallback('copy', MultiColumnWizard.copyClick) MultiColumnWizard.addOperationLoadCallback('delete', MultiColumnWizard.deleteLoad); MultiColumnWizard.addOperationClickCallback('delete', MultiColumnWizard.deleteClick); MultiColumnWizard.addOperationClickCallback('up', MultiColumnWizard.upClick); -MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); +MultiColumnWizard.addOperationClickCallback('down', MultiColumnWizard.downClick); \ No newline at end of file From d779d0251d9bf3585d51b1584c20fb0e5af78638 Mon Sep 17 00:00:00 2001 From: David Maack Date: Mon, 30 Apr 2012 10:49:21 +0200 Subject: [PATCH 21/21] Update readme.md (fix syntaxhighlighting) --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index ef9c17b..ade93b5 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Usage with columnFields =============

+ &$GLOBALS['TL_LANG']['tl_theme']['templateSelection'],
@@ -37,12 +39,16 @@ $GLOBALS['TL_DCA']['tl_theme']['fields']['templateSelection'] = array
             )
         )
 );
+
+?>
 
Usage with callback =============

+ &$GLOBALS['TL_LANG']['tl_table']['anything'],
@@ -54,6 +60,8 @@ $GLOBALS['TL_DCA']['tl_table']['fields']['anything'] = array
         'columnsCallback'       => array('Class', 'Method')
         )
 );
+
+?>
 
More information