Сортировка drag'n'drop в свойствах товаров
Зачастую в некоторых проектах требуется поддержка сортировки в комбобоксах. Требуется это по разным причинам, в частности, это и хотелки заказчика, и требования сортировки в ручном режиме для каждого товара, и т.п. странные пожелания.
Представляю сообществу решение данной задачи, которую также кинул в pr в репозиторий minishop2:
— создаем директорию assets/components/minishop2/js/mgr/vendor/ и копируем в неё файл Sortable.js( взять можно по ссылке )
— открываем и редактируем файлы core/components/minishop2/controllers/product/create.class.php и core/components/minishop2/controllers/product/update.class.php, вставляем после
PS
второй мой готовый рецепт размещаю в Вопросах, т.к. не хватает рейтинга для размещения в Готовых рецептах :( Можно сказать это первые мои посты в сообществе.
Представляю сообществу решение данной задачи, которую также кинул в pr в репозиторий minishop2:
— создаем директорию assets/components/minishop2/js/mgr/vendor/ и копируем в неё файл Sortable.js( взять можно по ссылке )
— открываем и редактируем файлы core/components/minishop2/controllers/product/create.class.php и core/components/minishop2/controllers/product/update.class.php, вставляем после
$this->addJavascript($assetsUrl . 'js/mgr/minishop2.js');
строку $this->addJavascript($assetsUrl . 'js/mgr/vendor/Sortable.js');
— редактируем файл assets/components/minishop2/js/mgr/misc/ms2.combo.js, а именно меняем:miniShop2.combo.Options = function (config) {
config = config || {};
Ext.applyIf(config, {
xtype: 'superboxselect',
allowBlank: true,
msgTarget: 'under',
allowAddNewData: true,
addNewDataOnBlur: true,
pinList: false,
resizable: true,
name: config.name || 'tags',
anchor: '100%',
minChars: 1,
store: new Ext.data.JsonStore({
id: (config.name || 'tags') + '-store',
root: 'results',
autoLoad: false,
autoSave: false,
totalProperty: 'total',
fields: ['value'],
url: miniShop2.config['connector_url'],
baseParams: {
action: 'mgr/product/getoptions',
key: config.name
}
}),
mode: 'remote',
displayField: 'value',
valueField: 'value',
triggerAction: 'all',
extraItemCls: 'x-tag',
expandBtnCls: 'x-form-trigger',
clearBtnCls: 'x-form-trigger',
});
config.name += '[]';
Ext.apply(config, {
listeners: {
newitem: function(bs, v) {
bs.addNewItem({value: v});
},
},
});
miniShop2.combo.Options.superclass.constructor.call(this, config);
};
Ext.extend(miniShop2.combo.Options, Ext.ux.form.SuperBoxSelect);
Ext.reg('minishop2-combo-options', miniShop2.combo.Options);
на следующее:miniShop2.combo.Options = function (config) {
config = config || {};
Ext.applyIf(config, {
xtype: 'superboxselect',
allowBlank: true,
msgTarget: 'under',
allowAddNewData: true,
addNewDataOnBlur: true,
pinList: false,
resizable: true,
name: config.name || 'tags',
anchor: '100%',
minChars: 1,
store: new Ext.data.JsonStore({
id: (config.name || 'tags') + '-store',
root: 'results',
autoLoad: false,
autoSave: false,
totalProperty: 'total',
fields: ['value'],
url: miniShop2.config['connector_url'],
baseParams: {
action: 'mgr/product/getoptions',
key: config.name
}
}),
mode: 'remote',
displayField: 'value',
valueField: 'value',
triggerAction: 'all',
extraItemCls: 'x-tag',
expandBtnCls: 'x-form-trigger',
clearBtnCls: 'x-form-trigger',
});
config.name += '[]';
Ext.apply(config, {
listeners: {
afterrender: {
fn: this.afterrender,
scope: this
},
newitem: {
fn: this.newitem,
scope: this
}
}
});
miniShop2.combo.Options.superclass.constructor.call(this, config);
};
miniShop2.combo.Options = Ext.extend(miniShop2.combo.Options, Ext.ux.form.SuperBoxSelect, {
newitem: function(bs, v) {
bs.addNewItem({value: v});
},
afterrender: function () {
var _this = this;
console.log(_this);
var item = document.querySelectorAll("#" + this.outerWrapEl.id + " ul")[0];
if (item) {
item.setAttribute("data-xcomponentid", this.id);
new Sortable(item, {
onEnd: function (evt) {
if (evt.currentTarget) {
var cmpId = evt.currentTarget.getAttribute("data-xcomponentid");
var cmp = Ext.getCmp(cmpId);
if (cmp) {
_this.refreshSorting(cmp);
MODx.fireResourceFormChange();
} else {
console.log("Unable to reference xComponentContext.");
}
}
}
});
} else {
console.log("Unable to find select element");
}
},
refreshSorting: function (cmp) {
var viewList = cmp.items.items;
var dataInputList = document.querySelectorAll("#" + cmp.outerWrapEl.dom.id + " .x-superboxselect-input");
var getElementIndex = function (item) {
var nodeList = Array.prototype.slice.call(item.parentElement.children);
return nodeList.indexOf(item);
};
var getElementByIndex = function (index) {
return nodeList[index];
};
var getElementByValue = function (val, list) {
for (var i = 0; i < list.length; i += 1) {
if (list[i].value == val) {
return list[i];
}
}
};
var sortElementsByListIndex = function (list, callback) {
list.sort(compare);
if (callback instanceof Function) {
callback();
}
};
var syncElementsByValue = function (list1, list2, callback) {
var targetListRootElement = list2[0].parentElement;
if (targetListRootElement) {
for (var i = 0; i < list1.length; i += 1) {
var targetItemIndex;
var item = list1[i];
var targetItem = getElementByValue(item.value, list2);
var initialTargetElement = list2[i];
if (targetItem !== null && initialTargetElement !== undefined) {
targetListRootElement.insertBefore(targetItem, initialTargetElement);
}
}
} else {
console.debug("syncElementsByValue(), Unable to reference list root element.");
return false;
}
if (callback instanceof Function) {
callback();
}
};
var compare = function (a, b) {
var aIndex = getElementIndex(a.el.dom);
var bIndex = getElementIndex(b.el.dom);
if (aIndex < bIndex) {
return -1;
}
if (aIndex > bIndex) {
return 1;
}
return 0;
};
sortElementsByListIndex(viewList);
syncElementsByValue(viewList, dataInputList[0].children);
cmp.value = cmp.getValue();
},
});
Ext.reg('minishop2-combo-options', miniShop2.combo.Options);
Пишу сюда в рецепты для случая если pull request отклонят, тогда данное решение останется и всегда будет доступно для поиска заинтересованным.PS
второй мой готовый рецепт размещаю в Вопросах, т.к. не хватает рейтинга для размещения в Готовых рецептах :( Можно сказать это первые мои посты в сообществе.
Комментарии: 1
ну по уму то делать без сторонних плагинов. Есть же service.cnxcorp.com/ext-4.1.1/docs/index.html#!/api/Ext.dd.DD
а так молодец! )
а так молодец! )
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.