diff --git a/README.md b/README.md index 3ada39c..37cd1c3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # mm_ddMultipleFields +**This is NOT Original mm_ddMultipleFields** + +To explore original mm_ddMultipleFields from DivanDesign go to original repo that forked +[DivanDesign/MODXEvo.plugin.ManagerManager.mm_ddMultipleFields](https://github.com/DivanDesign/MODXEvo.plugin.ManagerManager.mm_ddMultipleFields) + + Widget for plugin ManagerManager that allows you to add any number of fields values (TV) in one document (values is written as one with using separator symbols). For example: a few images. -___ -Visit the following [link](http://code.divandesign.biz/modx/mm_ddmultiplefields) to read the documentation, instructions & changelog. \ No newline at end of file + +See more info inside [ddmultiplefields.php](https://github.com/MrSwed/MODXEvo.plugin.ManagerManager.mm_ddMultipleFields/blob/master/ddmultiplefields/ddmultiplefields.php#L1-L32) +and in [Modx.im blog](http://modx.im/blog/addons/4265.html) diff --git a/ddmultiplefields/ddmultiplefields.css b/ddmultiplefields/ddmultiplefields.css index 8d45bd8..05be613 100644 --- a/ddmultiplefields/ddmultiplefields.css +++ b/ddmultiplefields/ddmultiplefields.css @@ -17,7 +17,7 @@ font: 12px/1.2em Verdana,Helvetica,sans-serif !important; } -.ddMultipleField input {height: 1.2em;} +.ddMultipleField input {height: 2em;} .ddMultipleField input:focus {border-color: #E1A020 !important;} @@ -39,11 +39,15 @@ vertical-align: top; } -.ddMultipleField tr th, .ddMultipleField tr td.ddFieldCol:last-child { +.ddMultipleField tr td.ddFieldCol:last-child { white-space: nowrap; } -.ddMultipleField tr th {text-align: left;} +.ddMultipleField tr th { + line-height: 1; + text-align: left; + vertical-align: bottom; +} .ddMultipleField tr td.ddFieldCol, .ddMultipleField tr td.ddSortHandle { border: 2px solid #FFFFFF; @@ -70,8 +74,8 @@ .ddMultipleField tr td.ddSortHandle div { /* border-radius: 0 12px 12px 0; */ background: #007CC3; - width: 10px; - height: 23px; + min-width: 1em; + min-height: 2em; -webkit-transition: opacity 0.3s ease-out; -moz-transition: opacity 0.3s ease-out; -ms-transition: opacity 0.3s ease-out; @@ -79,6 +83,13 @@ transition: opacity 0.3s ease-out; opacity: .3; cursor: n-resize; + color: white; + display: inline-block; + padding: 0.2em 0.3em 0.2em 0.25em; + box-sizing: border-box; +} +.ddMultipleField.nosort tr td.ddSortHandle div { + cursor: default; } .ddMultipleField tr.ddFieldBlock:hover td.ddFieldCol, .ddMultipleField tr.ddFieldBlock:hover td.ddSortHandle {background: #B2E3FF;} @@ -98,4 +109,16 @@ background: #f0f0f0; width: 100%; height: 100%; -} \ No newline at end of file +} +.tip { + cursor: default; +} +.tip:after { + color: #999; + content: "?"; + display: inline-block; + font-size: 80%; + padding: 0.05em 0.15em; + text-align: center; + vertical-align: super; +} diff --git a/ddmultiplefields/ddmultiplefields.php b/ddmultiplefields/ddmultiplefields.php index 1d20c13..3af1f67 100644 --- a/ddmultiplefields/ddmultiplefields.php +++ b/ddmultiplefields/ddmultiplefields.php @@ -1,7 +1,7 @@ Event; $output = ''; $site = $modx->config['site_url']; - $widgetDir = $site.'assets/plugins/managermanager/widgets/ddmultiplefields/'; + $widgetPath = 'assets/plugins/managermanager/widgets/ddmultiplefields/'; + $widgetDir = $site.$widgetPath; if ($e->name == 'OnDocFormPrerender'){ global $_lang; - - $output .= includeJsCss($site.'assets/plugins/managermanager/js/jquery-ui-1.10.3.min.js', 'html', 'jquery-ui', '1.10.3'); + ddTools::extendLanguage($widgetPath); + $usedLangKeys = array("insert","edit","clean","confirm_delete_record","batch_filling","clone_row","raw_btn_tip","reset"); + $usedLangKeys = array_combine($usedLangKeys, $usedLangKeys); + $usedLang = array_intersect_key($_lang,$usedLangKeys); + + $output .= includeJsCss($site.'assets/plugins/managermanager/js/jquery-ui.min.js', 'html', 'jquery-ui', '1.12.1'); $output .= includeJsCss($widgetDir.'ddmultiplefields.css', 'html'); $output .= includeJsCss($widgetDir.'jquery.ddMM.mm_ddMultipleFields.js', 'html', 'jquery.ddMM.mm_ddMultipleFields', '1.1.1'); - $output .= includeJsCss('$j.ddMM.lang.edit = "'.$_lang['edit'].'";', 'html', 'mm_ddMultipleFields_plain', '1', true, 'js'); - + $output .= includeJsCss('$j.ddMM.lang = '.json_encode($usedLang).';', 'html', 'mm_ddMultipleFields_plain', '1', true, 'js'); + $e->output($output); }else if ($e->name == 'OnDocFormRender'){ global $mm_current_page; @@ -59,16 +72,17 @@ function mm_ddMultipleFields($tvs = '', $roles = '', $templates = '', $columns = $columnsData = array(); foreach ($columnsDataTemp as $value){ - //Евалим знение и записываем результат или исходное значени - $eval = @eval($value); - $columnsData[] = $eval ? addslashes(json_encode($eval)) : addslashes($value); + //Проверяем значение и записываем результат или исходное значени + $columnsData[] = addslashes(!isJson($value) ? json_encode($value) : $value); } //Сливаем в строку, что бы передать на клиент $columnsData = implode('||', $columnsData); } //Стиль превью изображения - $stylePrewiew = "max-width:{$imgW}px; max-height:{$imgH}px; margin: 4px 0; cursor: pointer;"; + $imgW = $imgW.(is_numeric($imgW)?"px":""); + $imgH = $imgH.(is_numeric($imgH)?"px":""); + $stylePrewiew = "max-width:{$imgW}; max-height:{$imgH}; margin: 4px 0; cursor: pointer;"; $tvsMas = tplUseTvs($mm_current_page['template'], $tvs, 'image,file,text,email,textarea', 'id,type'); if ($tvsMas == false){return;} @@ -100,7 +114,8 @@ function mm_ddMultipleFields($tvs = '', $roles = '', $templates = '', $columns = colWidth: "'.$colWidth.'", imageStyle: "'.$stylePrewiew.'", minRow: "'.$minRow.'", - maxRow: "'.$maxRow.'" + maxRow: "'.$maxRow.'", + options: '.$options.' }); '; } diff --git a/ddmultiplefields/jquery.ddMM.mm_ddMultipleFields.js b/ddmultiplefields/jquery.ddMM.mm_ddMultipleFields.js index 24acd5f..7cca6d3 100644 --- a/ddmultiplefields/jquery.ddMM.mm_ddMultipleFields.js +++ b/ddmultiplefields/jquery.ddMM.mm_ddMultipleFields.js @@ -30,7 +30,14 @@ $.ddMM.mm_ddMultipleFields = { //Минимальное количество строк minRow: 0, //Максимальное количество строк - maxRow: 0 + maxRow: 0, + //Различные опции + options: { + sortable: true, + showIndex: true, + btnToggleRaw: false, + hideCommonControl: false + } }, // Все экземпляры (TV). Структура: { // 'id': { @@ -43,62 +50,65 @@ $.ddMM.mm_ddMultipleFields = { richtextWindow: null, //Обновляет мульти-поле, берёт значение из оригинального поля updateField: function(id){ - var _this = this; - + var _inst = this.instances[id]; //Если есть текущее поле - if (_this.instances[id].currentField){ + if (_inst.currentField){ //Задаём значение текущему полю (берём у оригинального поля), запускаем событие изменения - _this.instances[id].currentField.val($.trim($('#' + id).val())).trigger('change.ddEvents'); + _inst.currentField.val($.trim($('#' + id).val())).trigger('change.ddEvents'); //Забываем текущее поле (ибо уже обработали) - _this.instances[id].currentField = false; + _inst.currentField = false; } }, + _getRowFields: function(id,ddFieldBlock,id_field) { + var _inst = this.instances[id], + masCol = []; + + //Перебираем все колонки, закидываем значения в массив + $(ddFieldBlock).find('.ddField').each(function(index){ + //Если поле с типом id + if (typeof id_field !=="undefined" && _inst.coloumns[index] == 'id'){ + id_field.index = index; + id_field.$field = $(this); + + //Сохраняем значение поля + id_field.val = id_field.$field.val(); + //Если значение пустое, то генерим + if (id_field.val == ''){id_field.val = (new Date).getTime();} + + //Обнуляем значение + id_field.$field.val(''); + } + //Если колонка типа richtext + if (_inst.coloumns[index] == 'richtext'){ + //Собираем значения строки в массив + masCol.push($.trim($(this).html())); + }else{ + //Собираем значения строки в массив + masCol.push($.trim($(this).val())); + } + }); + return masCol; + }, //Обновляет оригинальное поле TV, собирая данные по мульти-полям updateTv: function(id){ - var _this = this, - masRows = new Array(); + var _this = this, + _inst = _this.instances[id], + masRows = []; //Перебираем все строки $('#' + id + 'ddMultipleField .ddFieldBlock').each(function(){ - var $this = $(this), - masCol = new Array(), - id_field = { + var id_field = { index: false, val: false, $field: false }; - - //Перебираем все колонки, закидываем значения в массив - $this.find('.ddField').each(function(index){ - //Если поле с типом id TODO: Какой смысл по всех этих манипуляциях? - if (_this.instances[id].coloumns[index] == 'id'){ - id_field.index = index; - id_field.$field = $(this); - - //Сохраняем значение поля - id_field.val = id_field.$field.val(); - //Если значение пустое, то генерим - if (id_field.val == ''){id_field.val = (new Date).getTime();} - - //Обнуляем значение - id_field.$field.val(''); - } - - //Если колонка типа richtext - if (_this.instances[id].coloumns[index] == 'richtext'){ - //Собираем значения строки в массив - masCol.push($.trim($(this).html())); - }else{ - //Собираем значения строки в массив - masCol.push($.trim($(this).val())); - } - }); + var masCol = _this._getRowFields(id,this,id_field); //Склеиваем значения колонок через разделитель - var col = masCol.join(_this.instances[id].splX); + var col = masCol.join(_inst.splX); //Если значение было хоть в одной колонке из всех в этой строке - if (col.length != ((masCol.length - 1) * _this.instances[id].splX.length)){ + if (col.length != ((masCol.length - 1) * _inst.splX.length)){ //Проверяем было ли поле с id if (id_field.index !== false){ //Записываем значение в поле @@ -106,7 +116,7 @@ $.ddMM.mm_ddMultipleFields = { //Обновляем значение в массиве masCol[id_field.index] = id_field.val; //Пересобираем строку - col = masCol.join(_this.instances[id].splX); + col = masCol.join(_inst.splX); } masRows.push(col); @@ -114,62 +124,105 @@ $.ddMM.mm_ddMultipleFields = { }); //Записываем значение в оригинальное поле - $('#' + id).val(masRows.join(_this.instances[id].splY)); + $('#' + id).val(masRows.join(_inst.splY)); + }, + // Сброс на сохраненные значения (аналог reset form) + _reset: function(id) { + var _this = this; + var _parent; + $.each("ddMultipleFieldControl,ddMultipleField".split(","),function(i,v){ + if (!_parent) _parent=$('#'+id+v).parent(); + $('#'+id+v).remove(); + }); + if (_parent) return _this.init(id,$('#'+id,_parent).val(),_parent); }, //Инициализация //Принимает id оригинального поля, его значения и родителя поля init: function(id, val, target){ var _this = this, + _inst = _this.instances[id], + //Блок для общих управляющих элементов + $ddMultipleFieldControl = $('
').appendTo(target), //Делаем таблицу мульти-полей, вешаем на таблицу функцию обновления оригинального поля - $ddMultipleField = $('
').appendTo(target)/*.on('change.ddEvents', function(){_this.updateTv(id);})*/; - + $ddMultipleField = $('
').appendTo(target)/*.on('change.ddEvents', function(){_this.updateTv(id);})*/; + if (_inst.options.hideCommonControl) $ddMultipleFieldControl.hide(); + if (!(_inst.maxRow == 1 && _inst.minRow == 1)) { + //Кнопка очистки + $('').appendTo($ddMultipleFieldControl).on("click", function (e) { + e.preventDefault(); + if(confirm($.ddMM.lang.confirm_delete_record))$(".ddDeleteButton"+(_inst.minRow?":gt("+(_inst.minRow-1)+")":""), $ddMultipleField).click(); + }); + } + //Кнопка Reset + $('').appendTo($ddMultipleFieldControl).on("click", function (e) { + e.preventDefault(); + _this._reset(id); + }); + // Кнопка "Показать/скрыть исходное значение". Простая возможность скопировать и вставить значение всего поля. + if (_inst.options.btnToggleRaw) { + $('').appendTo($ddMultipleFieldControl).on("click", function (e) { + e.preventDefault(); + $('#' + id).toggle(); + }); + } //Если есть хоть один заголовок - if (_this.instances[id].coloumnsTitle.length > 0){ - var text = ''; + if (_inst.coloumnsTitle.length > 0){ + var _thead = [$("")]; //Создадим шапку (перебираем именно колонки!) - $.each(_this.instances[id].coloumns, function(key, val){ + $.each(_inst.coloumns, function(key, val){ //Если это колонка с id if (val == 'id'){ //Вставим пустое значение в массив с заголовками - _this.instances[id].coloumnsTitle.splice(key, 0, ''); - - text += ''; + _inst.coloumnsTitle.splice(key, 0, ''); + _thead.push(''); }else{ + var _cTitle; //Если такого значения нет — сделаем - if (!_this.instances[id].coloumnsTitle[key]){ - _this.instances[id].coloumnsTitle[key] = ''; - } - - text += '' + (_this.instances[id].coloumnsTitle[key]) + ''; + if (!(_cTitle=_inst.coloumnsTitle[key])){ + _cTitle = _inst.coloumnsTitle[key] = ''; + } + // Подсказка для заголовка - расширенный текст после разделителя + var _titles = _cTitle.split(_inst.splX); + if (_titles.length>1) { + _cTitle = _titles[0]; + _thead.push('' + (_cTitle) + ''); + } else + _thead.push('' + (_cTitle) + ''); } }); - - $('' + text + '').appendTo($ddMultipleField); + if (!(_inst.maxRow == 1 && _inst.minRow == 1)) _thead.push(''); + $("").append($("").append(_thead)).prependTo($ddMultipleField); } //Делаем новые мульти-поля - var arr = val.split(_this.instances[id].splY); - + var arr = val.split(_inst.splY); + //Проверяем на максимальное и минимальное количество строк - if (_this.instances[id].maxRow && arr.length > _this.instances[id].maxRow){ - arr.length = _this.instances[id].maxRow; - }else if (_this.instances[id].minRow && arr.length < _this.instances[id].minRow){ - arr.length = _this.instances[id].minRow; + if (_inst.maxRow && arr.length > _inst.maxRow){ + arr.length = _inst.maxRow; + }else if (_inst.minRow && arr.length < _inst.minRow){ + arr.length = _inst.minRow; } //Создаём кнопку + - _this.instances[id].$addButton = _this.makeAddButton(id); + _inst.$addButton = _this.makeAddButton(id); for (var i = 0, len = arr.length; i < len; i++){ - //В случае, если размер массива был увеличен по minRow, значением будет undefined, посему зафигачим пустую строку - _this.makeFieldRow(id, arr[i] || ''); + //В случае, если размер массива был увеличен по minRow, значением будет undefined, вот и замечательно - то что нужно + _this.makeFieldRow(id, arr[i]); } + // Если только одна строка, то закончили + if (_inst.maxRow == 1) { + return; + } + //Втыкаем кнопку + куда надо - _this.instances[id].$addButton.appendTo($('#' + id + 'ddMultipleField .ddFieldBlock:last .ddFieldCol:last')); + _this.moveAddButton(id); //Добавляем возможность перетаскивания + if (!_inst.options || _inst.options.sortable!==false) $ddMultipleField.sortable({ items: 'tr:has(td)', handle: '.ddSortHandle', @@ -177,70 +230,133 @@ $.ddMM.mm_ddMultipleFields = { axis: 'y', placeholder: 'ui-state-highlight', start: function(event, ui){ - ui.placeholder.html('
').find('div').css('height', ui.item.height()); + ui.placeholder.html('
').find('div').css('height', ui.item.height()); }, stop: function(event, ui){ //Находим родителя таблицы, вызываем функцию обновления поля _this.moveAddButton(id); } }); + // Возможность пакетного заполнения + var batchFields = ["image","file"]; + for (var k=0;k < _inst.coloumns.length; k++) + if ($.inArray(_inst.coloumns[k],batchFields)!=-1) { + _inst.batch={"type":this.instances[id].coloumns[k],"col":k}; + //Пока только для первого найденного + break; + } + if (_inst.batch) { + var BrowseServerMultiple = function (ctrl,type) { + type = (type!=('image'||'file')?"image":type)+"s"; + lastImageCtrl = ctrl; + var w = screen.width * 0.5; + var h = screen.height * 0.5; + OpenServerBrowser('media/browser/mcpuk/browse.php?opener=ddMultipleField&type='+type, w, h); + }; + $("").appendTo($ddMultipleFieldControl).click(function(e){ + e.preventDefault(); + window.KCFinder = { + callBackMultiple: function (files) { + window.KCFinder = null; + for (var i = 0; i < files.length; i++) { + var arr = []; + arr.length = _inst.coloumns.length; + arr[_inst.batch.col] = files[i]; + _this.makeFieldRow(id, arr); + } + _this.moveAddButton(id); + var checkEmpty = ""; + $(".ddFieldBlock:first input.ddField", $ddMultipleField).each(function () { + checkEmpty += $(this).val() + }); + if (!checkEmpty) $(".ddFieldBlock:first .ddDeleteButton", $ddMultipleField).click(); + }, + callBack: function (url) { + window.KCFinder.callBackMultiple([url]) + } + }; + BrowseServerMultiple(id,_inst.batch.type); + }); + } }, //Функция создания строки //Принимает id и данные строки - makeFieldRow: function(id, val){ + makeFieldRow: function(id, val,returnOnly){ var _this = this; - + var _inst = _this.instances[id]; + var _ddField = $('#' + id + 'ddMultipleField'); //Если задано максимальное количество строк - if (_this.instances[id].maxRow){ + if (_inst.maxRow){ //Общее количество строк на данный момент - var fieldBlocksLen = $('#' + id + 'ddMultipleField .ddFieldBlock').length; + var fieldBlocksLen = $('.ddFieldBlock',_ddField).length; //Проверяем превышает ли уже количество строк максимальное - if (_this.instances[id].maxRow && fieldBlocksLen >= _this.instances[id].maxRow){ + if (_inst.maxRow && fieldBlocksLen >= _inst.maxRow){ return; //Если будет равно максимуму при создании этого поля - }else if (_this.instances[id].maxRow && fieldBlocksLen + 1 == _this.instances[id].maxRow){ - _this.instances[id].$addButton.attr('disabled', true); + }else if (_inst.maxRow && fieldBlocksLen + 1 == _inst.maxRow){ + _inst.$addButton.attr('disabled', true); + $(".ddCloneButton",_ddField).attr("disabled",true); } } - var $fieldBlock = $('
').appendTo($('#' + id + 'ddMultipleField')); - + var $fieldBlock = $('
'); + if (_inst.options && _inst.options.sortable===false) _ddField.addClass("nosort"); + //Разбиваем переданное значение на колонки - val = val.split(_this.instances[id].splX); + val = val ? val :[]; + if (typeof val=="string") val=val.split(_inst.splX); var $field; //Перебираем колонки - $.each(_this.instances[id].coloumns, function(key){ - if (!val[key]){val[key] = '';} - if (!_this.instances[id].coloumnsTitle[key]){_this.instances[id].coloumnsTitle[key] = '';} - if (!_this.instances[id].colWidth[key] || _this.instances[id].colWidth[key] == ''){_this.instances[id].colWidth[key] = _this.instances[id].colWidth[key - 1];} + $.each(_inst.coloumns, function(key){ + _inst.coloumnsData[key] && (_inst.coloumnsDataDefault = _inst.coloumnsData[key]) || (_inst.coloumnsDataDefault && ( _inst.coloumnsData[key]=_inst.coloumnsDataDefault )); + var _cTitle = _inst.coloumnsTitle[key]?_inst.coloumnsTitle[key].split(_inst.splX)[0]:''; + if (typeof val[key]=='undefined'){ + //Значение по умолчанию. для JSON, искать флаг в 3-м элементе, или первое значение + if (val[key] = _inst.coloumnsData[key] || '' ) + try { + var valDef = val[key] = $.parseJSON(val[key]); + while($.isArray(valDef)) valDef=valDef.shift(); + $.each(val[key], function(k,v){ + if (v[2]) { + valDef = v[0]; + return false; + } + }); + val[key] = valDef; + } catch (e) {} + } + if (!_inst.colWidth[key] || _inst.colWidth[key] == ''){_inst.colWidth[key] = _inst.colWidth[key - 1];} var $col = _this.makeFieldCol($fieldBlock); //Если текущая колонка является изображением - if(_this.instances[id].coloumns[key] == 'image'){ - $field = _this.makeText(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].colWidth[key], $col); + switch(_inst.coloumns[key]) { + case 'image' : + $field = _this.makeText(val[key], _cTitle, _inst.colWidth[key], $col); _this.makeImage(id, $col); //Create Attach browse button - $('').insertAfter($field).on('click', function(){ - _this.instances[id].currentField = $(this).siblings('.ddField'); + $('').insertAfter($field).on('click', function(){ + _inst.currentField = $(this).siblings('.ddField'); BrowseServer(id); }); + break; //Если текущая колонка является файлом - }else if(_this.instances[id].coloumns[key] == 'file'){ - $field = _this.makeText(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].colWidth[key], $col); + case 'file': + $field = _this.makeText(val[key], _cTitle, _inst.colWidth[key], $col); //Create Attach browse button - $('').insertAfter($field).on('click', function(){ - _this.instances[id].currentField = $(this).siblings('.ddField'); + $('').insertAfter($field).on('click', function(){ + _inst.currentField = $(this).siblings('.ddField'); BrowseFileServer(id); }); + break; //Если id - }else if (_this.instances[id].coloumns[key] == 'id'){ + case 'id': $field = _this.makeText(val[key], '', 0, $col); if (!($field.val())){ @@ -248,32 +364,62 @@ $.ddMM.mm_ddMultipleFields = { } $col.hide(); + break; //Если селект - }else if(_this.instances[id].coloumns[key] == 'select'){ - _this.makeSelect(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].coloumnsData[key], _this.instances[id].colWidth[key], $col); + case 'select': + _this.makeSelect(val[key], _cTitle, _inst.coloumnsData[key], _inst.colWidth[key], $col); + break; + //Если мультиселект + case 'multiselect': + _this.makeSelect(val[key], _cTitle, _inst.coloumnsData[key], _inst.colWidth[key], $col,true); + break; //Если дата - }else if(_this.instances[id].coloumns[key] == 'date'){ - _this.makeDate(val[key], _this.instances[id].coloumnsTitle[key], $col); + case 'date': + _this.makeDate(val[key], _cTitle, $col); + break; //Если textarea - }else if(_this.instances[id].coloumns[key] == 'textarea'){ - _this.makeTextarea(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].colWidth[key], $col); + case 'textarea': + _this.makeTextarea(val[key], _cTitle, _inst.colWidth[key], $col); //Если richtext - }else if(_this.instances[id].coloumns[key] == 'richtext'){ - _this.makeRichtext(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].colWidth[key], $col); + break; + case 'richtext': + _this.makeRichtext(val[key], _cTitle, _inst.colWidth[key], $col); + break; + case 'number': + _this.makeNumber(val[key], _cTitle, _inst.colWidth[key], $col); + break; //По дефолту делаем текстовое поле - }else{ - _this.makeText(val[key], _this.instances[id].coloumnsTitle[key], _this.instances[id].colWidth[key], $col); + default: + _this.makeText(val[key], _cTitle, _inst.colWidth[key], $col); } }); - - //Create DeleteButton - _this.makeDeleteButton(id, _this.makeFieldCol($fieldBlock)); - + + // Если не одна обязательная строка + if (!(_inst.maxRow == 1 && _inst.minRow == 1)) { + //Create DeleteButton + _this.makeDeleteButton(id, _this.makeFieldCol($fieldBlock)); + + //Создаём кнопку copy + _inst.maxRow!=1 && _this.makeCopyButton(id).appendTo($('.ddFieldCol:last', $fieldBlock)); + } + //Специально для полей, содержащих изображения необходимо инициализировать $('.ddFieldCol:has(.ddField_image) .ddField', $fieldBlock).trigger('change.ddEvents'); + if (!returnOnly) $fieldBlock.appendTo($(">tbody",_ddField)); + _this.numberingRows(id); return $fieldBlock; }, + //Нумерация строк + numberingRows: function(id){ + var _inst = this.instances[id]; + if (_inst.options && _inst.options.showIndex===false) return; + var _ddField = $('#' + id + 'ddMultipleField'); + $(">tbody tr",_ddField).each(function(){ + var t=$(this); + t.find("td:first *:not(:has(*))").html(t.index()+1); + }) + }, //Создание колонки поля makeFieldCol: function($fieldRow){ return $('').appendTo($fieldRow); @@ -281,23 +427,20 @@ $.ddMM.mm_ddMultipleFields = { //Make delete button makeDeleteButton: function(id, $fieldCol){ var _this = this; - + var _inst = _this.instances[id]; + var _MField = $('#' + id + 'ddMultipleField'); + var _MFieldControl = $('#' + id + 'ddMultipleFieldControl'); $('').appendTo($fieldCol).on('click', function(){ //Проверяем на минимальное количество строк - if (_this.instances[id].minRow && $('#' + id + 'ddMultipleField .ddFieldBlock').length <= _this.instances[id].minRow){ + if (_inst.minRow && $('.ddFieldBlock',_MField).length <= _inst.minRow){ return; } var $this = $(this), $par = $this.parents('.ddFieldBlock:first')/*, $table = $this.parents('.ddMultipleField:first')*/; - - //Отчистим значения полей - $par.find('.ddField').val(''); - - //Если больше одной строки, то можно удалить текущую строчку - if ($par.siblings('.ddFieldBlock').length > 0){ $par.fadeOut(300, function(){ + var $siblingsL = $par.siblings('.ddFieldBlock').length; //Если контейнер имеет кнопку добалвения, перенесём её if ($par.find('.ddAddButton').length > 0){ _this.moveAddButton(id, $par.prev('.ddFieldBlock')); @@ -307,11 +450,22 @@ $.ddMM.mm_ddMultipleFields = { $par.remove(); //При любом удалении показываем кнопку добавления - _this.instances[id].$addButton.removeAttr('disabled'); + _inst.$addButton.removeAttr('disabled'); + $(".ddCloneButton",_MField).removeAttr("disabled"); - return; + //Если было меньше одной строки, созданем новую строчку + if (!$siblingsL){ + if (_inst.maxRow > 1 ) _inst.$addButton = _this.makeAddButton(id); + _this.makeFieldRow(id); + if (_inst.maxRow > 1 ) _this.moveAddButton(id); + } else if (_inst.minRow && $siblingsL <= _inst.minRow) { + $([_MFieldControl,_MField]).each(function(){$('.ddDeleteButton',this).attr("disabled","disabled");}); + } }); - } + }); + // Для всех созданных кнопок проверяем состояние + $([_MFieldControl,_MField,$fieldCol]).each(function(){ + $(".ddDeleteButton",this).attr("disabled",(_inst.minRow && $('.ddFieldBlock',_MField).length < _inst.minRow) ? "disabled" : false); }); }, //Функция создания кнопки +, вызывается при инициализации @@ -320,12 +474,36 @@ $.ddMM.mm_ddMultipleFields = { return $('').on('click', function(){ //Вешаем на кнопку создание новой строки - $(this).appendTo(_this.makeFieldRow(id, '').find('.ddFieldCol:last')); + $(this).appendTo(_this.makeFieldRow(id).find('.ddFieldCol:last')); + }); + }, + //Кнопка копирования строки + makeCopyButton: function (id) { + //Вешаем на кнопку создание дубликата текущей строки + var _this = this; + var fieldBlocks = $('#' + id + 'ddMultipleField .ddFieldBlock'); + var fieldBlocksLen = fieldBlocks.length; + var _inst = _this.instances[id]; + return $('').attr({ + "class": "ddCloneButton", + "type": "button", + "value": "©", + "title": $.ddMM.lang.clone_row, + "disabled": (_inst.maxRow && fieldBlocksLen + 1 == _inst.maxRow) ? "disabled" : false + }).on('click', function () { + if ($(this).attr("disabled")) return false; + var ddFieldBlock = $(this).closest("tr"); + var rowData = _this._getRowFields(id,ddFieldBlock); + ddFieldBlock.after(_this.makeFieldRow(id,rowData,false)); + _this.moveAddButton(id); + if (_inst.maxRow && fieldBlocksLen + 1 == _inst.maxRow) { + $(".ddCloneButton,.ddAddButton", '#' + id + 'ddMultipleField').attr("disabled", true) + } }); }, //Перемещение кнопки + moveAddButton: function(id, $target){ - var _this = this; + var _inst = this.instances[id]; //Если не передали, куда вставлять, вставляем в самый конец if (!$target){ @@ -333,14 +511,23 @@ $.ddMM.mm_ddMultipleFields = { } //Находим кнопку добавления и переносим куда надо - _this.instances[id].$addButton.appendTo($target.find('.ddFieldCol:last')); + _inst.$addButton.appendTo($target.find('.ddFieldCol:last')); + }, + //Checking size values. Make it universal + _united:function(v,out){ + if (!v) return v; + v = v+($.isNumeric(v)?"px":""); + return (/\%s/.test(out)?out.replace("%s",v):v); }, //Make text field makeText: function(value, title, width, $fieldCol){ - var $field = $(''); + var $field = $(''); return $field.val(value).appendTo($fieldCol); }, + makeNumber: function(value, title, width, $fieldCol){ + return $('').appendTo($fieldCol); + }, //Make date field makeDate: function(value, title, $fieldCol){ //name нужен для DatePicker`а @@ -355,19 +542,19 @@ $.ddMM.mm_ddMultipleFields = { }, //Make textarea field makeTextarea: function(value, title, width, $fieldCol){ - return $('').appendTo($fieldCol); + return $('').appendTo($fieldCol); }, //Make richtext field makeRichtext: function(value, title, width, $fieldCol){ var _this = this, - $field = $('
' + value + '
').appendTo($fieldCol); + $field = $('
' + value + '
').appendTo($fieldCol); $('
' + $.ddMM.lang.edit + '
').appendTo($fieldCol).find('a').on('click', function(event){ _this.richtextWindow = window.open($.ddMM.config.site_url + $.ddMM.urls.mm + 'widgets/ddmultiplefields/richtext/index.php', 'mm_ddMultipleFields_richtext', new Array( - 'width=600', - 'height=550', - 'left=' + (($.ddTools.windowWidth - 600) / 2), - 'top=' + (($.ddTools.windowHeight - 550) / 2), + 'width=900', + 'height=560', + 'left=' + (($.ddTools.windowWidth - 900) / 2), + 'top=' + (($.ddTools.windowHeight - 560) / 2), 'menubar=no', 'toolbar=no', 'location=no', @@ -388,9 +575,9 @@ $.ddMM.mm_ddMultipleFields = { //Make image field makeImage: function(id, $fieldCol){ var _this = this; - + var _inst = _this.instances[id]; // Create a new preview and Attach a browse event to the picture, so it can trigger too - $('
').appendTo($fieldCol).hide().find('img').on('click', function(){ + $('
').appendTo($fieldCol).hide().find('img').on('click', function(){ $fieldCol.find('.ddAttachButton').trigger('click'); }).on('load.ddEvents', function(){ //Удаление дерьма, блеать (превьюшка, оставленная от виджета showimagetvs) @@ -414,8 +601,8 @@ $.ddMM.mm_ddMultipleFields = { }); }, //Функция создания списка - makeSelect: function(value, title, data, width, $fieldCol){ - var $select = $(''); if (data){ var dataMas = $.parseJSON(data), @@ -428,7 +615,7 @@ $.ddMM.mm_ddMultipleFields = { $select.append(options); } - if (value){$select.val(value);} + if (value) {$select.val($multiple?value.split(","):value);} return $select.appendTo($fieldCol); }, diff --git a/ddmultiplefields/lang/english.inc.php b/ddmultiplefields/lang/english.inc.php new file mode 100644 index 0000000..05e8691 --- /dev/null +++ b/ddmultiplefields/lang/english.inc.php @@ -0,0 +1,22 @@ + "Batch Filling", + "clone_row" => "Clone row", + "raw_btn_tip" => "Show/hide original field. Available copying and pasting. After insertion, press the reset button. Attention! Wrong original field format can result in unpredictable consequences!", + "clean" => "Clean", + "reset" => "Reset" + +)); +?> \ No newline at end of file diff --git a/ddmultiplefields/lang/russian-UTF8.inc.php b/ddmultiplefields/lang/russian-UTF8.inc.php new file mode 100644 index 0000000..db7427b --- /dev/null +++ b/ddmultiplefields/lang/russian-UTF8.inc.php @@ -0,0 +1,21 @@ + "Пакетное заполнение", + "clone_row" => "Клонировать строку", + "raw_btn_tip"=>"Показать/Скрыть оригинальное поле. Доступны стандартные копирование и вставка. После вставки, нажмите кнопку сброса. Внимание! Неправильный формат исходного поля может привести к непредсказуемым последствиям!", + "clean" => "Очистить", + "reset" => "Сбросить" +)); +?> \ No newline at end of file diff --git a/ddmultiplefields/lang/russian.php b/ddmultiplefields/lang/russian.php new file mode 100644 index 0000000..8a3f3cf --- /dev/null +++ b/ddmultiplefields/lang/russian.php @@ -0,0 +1,9 @@ +' . $contents); + $modx_lang_attribute = 'ru'; // Manager HTML/XML Language Attribute see http://en.wikipedia.org/wiki/ISO_639-1 + $modx_manager_charset = 'windows-1251'; + setlocale (LC_ALL, 'ru_RU.CP1251'); +?> \ No newline at end of file diff --git a/ddmultiplefields/richtext/index.php b/ddmultiplefields/richtext/index.php index e5fcd92..5755ba9 100644 --- a/ddmultiplefields/richtext/index.php +++ b/ddmultiplefields/richtext/index.php @@ -37,7 +37,7 @@ require_once($modx->config['base_path'].$mmDir.'modx.ddtools.class.php'); $temp = $modx->invokeEvent('OnRichTextEditorInit', array( - 'editor' => 'TinyMCE', + 'editor' => $modx->config['which_editor'], 'elements' => array('ddMultipleFields_richtext') )); diff --git a/ddmultiplefields/richtext/script.js b/ddmultiplefields/richtext/script.js index b62cd09..f8d13fd 100644 --- a/ddmultiplefields/richtext/script.js +++ b/ddmultiplefields/richtext/script.js @@ -1,15 +1,17 @@ $(function(){ var $textarea = $('#ddMultipleFields_richtext'); - + $textarea.val(window.$ddField.html()).trigger('change'); - + $('.js-ok').on('click', function(){ - tinyMCE.triggerSave(); + if (typeof tinyMCE != 'undefined') { + tinyMCE.triggerSave(); + } window.$ddField.html($textarea.val()); $textarea.val(''); window.close(); }); - + $('.js-cancel').on('click', function(){ $textarea.val(''); window.close(); diff --git a/ddmultiplefields/richtext/style.css b/ddmultiplefields/richtext/style.css index 0a5094f..8aaa7df 100644 --- a/ddmultiplefields/richtext/style.css +++ b/ddmultiplefields/richtext/style.css @@ -1,4 +1,16 @@ +html, body { + height: 100%; +} +textarea { + width: 100%; + min-height: 250px; + box-sizing: border-box; + height: calc( 100% - 45px ); +} .buttons { padding-top: 10px; text-align: right; +} +body > .mce-container { + box-sizing: border-box; } \ No newline at end of file diff --git a/ddmultiplefields/richtext/template.html b/ddmultiplefields/richtext/template.html index 42b5a53..72d334b 100644 --- a/ddmultiplefields/richtext/template.html +++ b/ddmultiplefields/richtext/template.html @@ -11,8 +11,8 @@ [+tinyMCE+] - +
- \ No newline at end of file +