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/README.md b/README.md index 82be880..16059cb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ Usage with columnFields ======================= -```php - + &$GLOBALS['TL_LANG']['tl_theme']['templateSelection'], @@ -38,14 +39,17 @@ $GLOBALS['TL_DCA']['tl_theme']['fields']['templateSelection'] = array ) ) ); + ?> -``` + + Usage with callback =================== -```php - + &$GLOBALS['TL_LANG']['tl_table']['anything'], @@ -57,8 +61,10 @@ $GLOBALS['TL_DCA']['tl_table']['fields']['anything'] = array 'columnsCallback' => array('Class', 'Method') ) ); + ?> -``` + + More information ================ 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 c3ab9d7..63433aa 100644 --- a/system/modules/multicolumnwizard/MultiColumnWizard.php +++ b/system/modules/multicolumnwizard/MultiColumnWizard.php @@ -27,6 +27,7 @@ * @package MultiColumnWizard * @license LGPL * @filesource + * @info tab is set to 4 whitespaces */ /** @@ -82,6 +83,12 @@ class MultiColumnWizard extends Widget implements uploadable */ protected $maxCount = 0; + /** + * Tableless + * @var boolean + */ + protected $blnTableless = false; + /** * Row specific data * @var array @@ -94,11 +101,12 @@ class MultiColumnWizard extends Widget implements uploadable */ protected $arrButtons = array('copy' => 'copy.gif', 'up' => 'up.gif', 'down' => 'down.gif', 'delete' => 'delete.gif'); + /** * Initialize the object * @param array */ - public function __construct($arrAttributes=false) + public function __construct($arrAttributes = false) { parent::__construct($arrAttributes); $this->import('Database'); @@ -110,6 +118,7 @@ public function __construct($arrAttributes=false) } } + /** * Add specific attributes * @param string @@ -182,16 +191,23 @@ public function __set($strKey, $varValue) $this->maxCount = $varValue; break; + case 'generateTableless': + $this->blnTableless = $varValue; + break; + default: parent::__set($strKey, $varValue); break; } } + protected function validator($varInput) { for ($i = 0; $i < count($varInput); $i++) { + $this->activeRow = $i; + // Walk every column foreach ($this->columnFields as $strKey => $arrField) { @@ -279,6 +295,7 @@ protected function validator($varInput) return $varInput; } + /** * Generate the widget and return it as string * @return string @@ -292,15 +309,16 @@ 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'; + $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/multicolumnwizard/html/js/multicolumnwizard_' . strtolower(TL_MODE) . '.js'; $GLOBALS['TL_CSS'][] = 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; - $strCommand = 'cmd_' . $this->strField; + $this->strCommand = 'cmd_' . $this->strField; // Change the order - if ($this->Input->get($strCommand) && is_numeric($this->Input->get('cid')) && $this->Input->get('id') == $this->currentRecord) + if ($this->Input->get($this->strCommand) && is_numeric($this->Input->get('cid')) && $this->Input->get('id') == $this->currentRecord) { - switch ($this->Input->get($strCommand)) + + switch ($this->Input->get($this->strCommand)) { case 'copy': $this->varValue = array_duplicate($this->varValue, $this->Input->get('cid')); @@ -330,7 +348,7 @@ public function generate() } // Reload the page - $this->redirect(preg_replace('/&(amp;)?cid=[^&]*/i', '', preg_replace('/&(amp;)?' . preg_quote($strCommand, '/') . '=[^&]*/i', '', $this->Environment->request))); + $this->redirect(preg_replace('/&(amp;)?cid=[^&]*/i', '', preg_replace('/&(amp;)?' . preg_quote($this->strCommand, '/') . '=[^&]*/i', '', $this->Environment->request))); } $arrUnique = array(); @@ -355,34 +373,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 @@ -391,12 +383,13 @@ public function generate() $intNumberOfRows = $this->minCount; } + $arrItems = array(); + // Add input fields for ($i = 0; $i < $intNumberOfRows; $i++) { - $arrItem = array(); + $this->activeRow = $i; $strHidden = ''; - $return .= ''; // Walk every column foreach ($this->columnFields as $strKey => $arrField) @@ -458,9 +451,9 @@ public function generate() break; } - /* $datepicker = ' + $datepicker = ' '; + + $datepicker = $this->getMcWDatePickerString($objWidget->id, $strKey, $rgxp); + + /* $datepicker = ''; */ - $datepicker = ''; } // Add custom wizard @@ -510,13 +506,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'], @@ -524,60 +520,88 @@ 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 ($this->blnTableless) ? $this->generateDiv($arrUnique, $arrDatepicker, $strHidden, $arrItems) : $this->generateTable($arrUnique, $arrDatepicker, $strHidden, $arrItems); + } - $return .= ''; - } - else + protected function getMcWDatePickerString($strId, $strKey, $rgxp) + { + if (version_compare(VERSION, '2.11', '<')) + { + $format = $GLOBALS['TL_CONFIG'][$rgxp . 'Format']; + switch ($rgxp) { - foreach ($arrItem as $itemKey => $itemValue) - { - $arrReturnItems[$itemKey] = '' . $itemValue['entry'] . ''; - } - - $return .= implode('', $arrReturnItems); - } - + case 'datim': + $time = ",\n timePicker:true"; + break; + case 'time': + $time = ",\n timePickerOnly:true"; + break; - $return .= ''; + return ' + '; } - - $return .= '
' . $objTemplate->parse() . 'buttonPos != '') ? ' valign="' . $this->buttonPos . '" ' : '') . '>' . $strHidden; + default: + $time = ''; + break; + } - // Add buttons - foreach ($this->arrButtons as $button => $image) + return ' + '; + } + else + { + $format = Date::formatToJs($GLOBALS['TL_CONFIG'][$rgxp . 'Format']); + switch ($rgxp) { + case 'datim': + $time = ",\n timePicker:true"; + break; - if ($image === false) - { - continue; - } + case 'time': + $time = ",\n pickOnly:\"time\""; + break; - $return .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + default: + $time = ''; + break; } - $return .= '
'; - - $return .= ''; - - return $return; } + /** * Initialize widget * @@ -592,7 +616,11 @@ public function generate() 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'] == '') { @@ -602,7 +630,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 @@ -615,7 +643,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 @@ -676,8 +704,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'])) @@ -704,6 +732,7 @@ protected function initializeWidget(&$arrField, $intRow, $strKey, $varValue) return $objWidget; } + /** * Add specific field data to a certain field in a certain row * @param integer row index @@ -715,6 +744,143 @@ 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 + 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 .=' + '; + + foreach ($arrItems as $k => $arrValue) + { + $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 .= '
'; + + $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 + 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($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 .= '' . $this->generateImage($image, $GLOBALS['TL_LANG'][$this->strTable]['wz_' . $button], 'class="tl_listwizard_img"') . ' '; + } + + return $return; + } } -?> 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/config/config.php b/system/modules/multicolumnwizard/config/config.php index 06fd3f3..f8e7158 100644 --- a/system/modules/multicolumnwizard/config/config.php +++ b/system/modules/multicolumnwizard/config/config.php @@ -21,12 +21,11 @@ * 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 */ $GLOBALS['BE_FFL']['multiColumnWizard'] = 'MultiColumnWizard'; - -?> \ No newline at end of file +$GLOBALS['TL_FFL']['multiColumnWizard'] = 'MultiColumnWizard'; \ 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;g0){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 new file mode 100644 index 0000000..6f43b03 --- /dev/null +++ b/system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js @@ -0,0 +1,574 @@ +/** + * 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: [], + 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) + { + + 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); + + }); + } + }, + + + /** + * 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); + } + }, + + /** + * @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.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_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 new file mode 100644 index 0000000..165e986 --- /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); \ 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 deleted file mode 100644 index 80d28f0..0000000 --- a/system/modules/multicolumnwizard/html/js/multicolumnwizard_src.js +++ /dev/null @@ -1,237 +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 = -{ - 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); - }); - - // rewrite attributes - tbody.getChildren().each(function(el,i){ - MultiColumnWizard.updateFields(el.getChildren(), i) - }); - - // 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,'')); - }); - - - // 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 ID,NAME,FOR attributes - * for the fields - */ - 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(); - - // reattach - if (datepickerFields.length > 1 || datepickerFields[0] != '') - { - for(var i=0; i