Денис Чубенко

Денис Чубенко

С нами с 02 марта 2017; Место в рейтинге пользователей: #611
Николай
21 февраля 2020, 21:00
1
+1
push это функция языка javascript. Для работы с массивами там есть несколько функций, например splice
Alexey
21 февраля 2020, 19:28
1
0
Николай, Сергей, спасибо огромное — всё получилось))

Есть ещё небольшой вопрос, подскажите, пожалуйста, если знаете. Вот плагин, расширяющий представление формы в админке:
<?php
switch ($modx->event->name) {
    case 'msOnManagerCustomCssJs':
        if ($page != 'orders') return;
		$modx->controller->addHtml("
            <script type='text/javascript'>
                Ext.ComponentMgr.onAvailable('minishop2-window-orderproduct-update', function() {
    				new_item ={
                            layout: 'column',
                            border: false,
                            anchor: '100%',
                            items: [{
                                columnWidth: 1,
                                layout: 'form',
                                defaults: {msgTarget: 'under'},
                                border: false,
                                items: [{
                                    xtype: 'textfield',
                                    fieldLabel: 'Размер',
                                    name: 'el_size_c',
                                    anchor: '100%'
                                }]
                            }]
                        }
    				this.fields.push(new_item);
                });                
            </script>
        ");
    	break;
}
Получается, что методом push он добавляет поле в конец формы, после поля «Опции товара» — joxi.ru/YmEZ4vqUJMGZb2
Есть какой-то метод, который позволяет добавлять поле после определенного поля, к примеру —
joxi.ru/brRN3vdtYOBJqr

Вот сама форма:
miniShop2.window.OrderProduct = function (config) {
    config = config || {};
    //console.log(config.id);
    Ext.applyIf(config, {
        title: _('ms2_menu_update'),
        width: 600,
        baseParams: {
            action: config.action || 'mgr/orders/product/update',
        },
        modal: true,
    });
    miniShop2.window.OrderProduct.superclass.constructor.call(this, config);
};
Ext.extend(miniShop2.window.OrderProduct, miniShop2.window.Default, {

    getFields: function () {
        return [
            {xtype: 'hidden', name: 'id'},
            {xtype: 'hidden', name: 'order_id'},
            {
                layout: 'column',
                border: false,
                anchor: '100%',
                items: [{
                    columnWidth: .3,
                    layout: 'form',
                    defaults: {msgTarget: 'under'},
                    border: false,
                    items: [{
                        xtype: 'numberfield',
                        fieldLabel: _('ms2_product_count'),
                        name: 'count',
                        anchor: '100%',
                        allowNegative: false,
                        allowBlank: false
                    }]
                }, {
                    columnWidth: .7,
                    layout: 'form',
                    defaults: {msgTarget: 'under'},
                    border: false,
                    items: [{
                        xtype: 'textfield',
                        fieldLabel: _('ms2_name'),
                        name: 'name',
                        anchor: '100%'
                    }]
                }]
            }, {
                layout: 'column',
                border: false,
                anchor: '100%',
                items: [{
                    columnWidth: .5,
                    layout: 'form',
                    defaults: {msgTarget: 'under'},
                    border: false,
                    items: [{
                        xtype: 'numberfield',
                        decimalPrecision: 2,
                        fieldLabel: _('ms2_product_price'),
                        name: 'price',
                        anchor: '100%'
                    }]
                }, {
                    columnWidth: .5,
                    layout: 'form',
                    defaults: {msgTarget: 'under'},
                    border: false,
                    items: [{
                        xtype: 'numberfield',
                        decimalPrecision: 3,
                        fieldLabel: _('ms2_product_weight'),
                        name: 'weight',
                        anchor: '100%'
                    }]
                }]
            },/* {
                //custom
                layout: 'column',
                border: false,
                anchor: '100%',
                items: [{
                    columnWidth: 1,
                    layout: 'form',
                    defaults: {msgTarget: 'under'},
                    border: false,
                    items: [{
                        xtype: 'textfield',
                        fieldLabel: 'Размер',
                        name: 'el_size_c',
                        anchor: '100%'
                    }]
                }]
                //custom
            },*/
            {xtype: 'textarea', fieldLabel: _('ms2_product_options'), name: 'options', height: 100, anchor: '100%'}
        ];
    },

    getKeys: function () {
        return [{
            key: Ext.EventObject.ENTER,
            shift: true,
            fn: function () {
                this.submit()
            }, scope: this
        }];
    },

});
Ext.reg('minishop2-window-orderproduct-update', miniShop2.window.OrderProduct);
Ilya Gureshidze
22 августа 2019, 12:07
2
+1
Как обычно: сам задал вопрос — сам отвечаю.
1. Добавил поля id_1C и id_parent_1C в modx_site_content
2. В плагине на OnMODXInit (у меня там куча полей для расширения разных классов)
написал
$modx->map['modResource']['fields']['id_1C'] = '';
    	$modx->map['modResource']['fields']['id_parent_1C'] = '';
    	$modx->map['modResource']['fieldMeta']['id_1C'] = array(
		'dbtype' => 'varchar',
		'precision' => 50,
		'phptype' => 'string',
		'null' => false,
		'default' => ''
	);
	$modx->map['modResource']['fieldMeta']['id_parent_1C'] = array(
		'dbtype' => 'varchar',
		'precision' => 50,
		'phptype' => 'string',
		'null' => false,
		'default' => ''
	);
3. В плагине на OnDocFormSave и onDocFormPrerender
switch ($modx->event->name) {
    case 'OnDocFormPrerender':
        $id_1C = '';
        $id_parent_1C = '';
        
        if (isset($scriptProperties['resource'])) {
            if (is_object($resource)) {
                $id_1C = $resource->get('id_1C');
                $id_parent_1C = $resource->get('id_parent_1C');
            }
        }
$modx->controller->addHtml(<<<HTML
<script>
    Ext.ComponentMgr.onAvailable('modx-resource-main-left', function(page) {
        page.on('beforerender', function() {
            page.insert(2,{
                xtype: 'textfield'
                ,name: 'id_1C'
                ,value: '{$id_1C}'
                ,anchor: '100%'
                ,layout: 'anchor'
                ,fieldLabel: 'ID 1C'
            });
            page.insert(3,{
                xtype: 'textfield'
                ,name: 'id_parent_1C'
                ,value: '{$id_parent_1C}'
                ,anchor: '100%'
                ,layout: 'anchor'
                ,fieldLabel: 'ID родителя 1C'
            });
        })
    });
</script>
HTML
);
        break;
        
    case 'OnDocFormSave':
        $resource->set('id_1C', $_POST['id_1C']);
        $resource->set('id_parent_1C', $_POST['id_parent_1C']);
        break;
}
return;
Все заработало.
Денис
23 мая 2019, 14:07
3
0
Я делал 2 выборки на странице, всё работало.
Можно попробовать вот так:

<div id="pdopage">
     [[!+page.nav]]
    <div class="rows">
      [[!pdoPage?
        &element=`getImageList`
        &tvname=`resourcealbum` 
        &tpl=`effects-img`
        &limit=`15`
        &ajaxMode=`button`
        &wrapperTpl = `effects_wrapper`
        &docid=`[[*id]]`
        &processTVs=`1`
    ]]
    </div>
        </div>

<!-- Меняем ID на pdopage2 и добавляем параметры &ajaxElem... -->

  <div id="pdopage2">
     [[!+nav.pagevar]]
    <div class="rows">
      [[!pdoPage?
        &element=`getImageList`
        &tvname=`resourcealbum1` 
        &tpl=`effects-img`
        &limit=`15`
        &ajaxMode=`button`
        &wrapperTpl = `colors_wrapper`
        &docid=`[[*id]]`
        &processTVs=`1`
        &pageNavVar= `nav.pagevar`
        &pageVarKey=`page1`
        
        &ajaxElemWrapper=`#pdopage2`
        &ajaxElemRows=`#pdopage2 .rows`
        &ajaxElemPagination=`#pdopage2 .pagination`
        &ajaxElemLink=`#pdopage2 .pagination a`
        &ajaxElemMore=`#pdopage2 .btn-more`
    ]]
    </div>
  </div>
UDAV
18 апреля 2019, 11:22
3
+6
Обычный translit тоже так может!
Настройка friendly_alias_restrict_chars делаем alphanumeric и получаем тоже самое, без лишнего мусора.
Наумов Алексей
11 марта 2019, 09:05
1
+1
Кнопками управлять так.
При объявлении окна, внутри
Ext.applyIf(config, {
после
fields: this.getFields(config)
добавляем еще кнопки (по умолчанию их 2 штуки, а вот вам пример на 4 штуки)
buttons: [
            {
                text: 'Моя кнопка',
                scope: this,
                handler: function () {
                    alert("Работает");
                }
            },
            {
                text: config.cancelBtnText || _('cancel'),
                scope: this,
                handler: function () {
                    config.closeAction !== 'close' ? this.hide() : this.close();
                }
            },
            {
                text: config.saveBtnText || _('save'),
                scope: this,
                handler: function () {
                    this.submit(false);
                }
            },
            {
                text: config.saveBtnText || _('save_and_close'),
                cls: 'primary-button',
                scope: this,
                handler: function () {
                    this.submit(true);
                }
            }
        ]
Андрей
09 января 2019, 10:07
2
+1
Передавайте значение этого плейсхолдера в вызов mFilter2.

У mfilter есть параметр prepareSnippet, в нем указывается сниппет который будет обрабатывать результаты выборки.

код сниппета
$item = array_merge(
  (array) $row,
  array(
    'customData' => $modx->getOption('customData', $scriptProperties, '')
  )
);

return json_encode($item);

Теперь в вызове mfilter добавьте данные из плейсхолдера
'prepareSnippet' => 'название_сниппета',
'customData' => [
    'example' => $_modx->getPlaceholder('example')
]

Теперь в чанке c товаром будет доступен плейсхолдер {$customData.example}
Денис
30 июля 2018, 13:27
1
+3
Сделайте что то вроде такого.
Создайте файл в /assets/components/minishop2/js/mgr/product и назовите его product.extends.js

Ext.override(miniShop2.panel.Product,{
    getFields: function (config) {
        var fields = [];
        var originals = MODx.panel.Resource.prototype.getFields.call(this, config);

        for (var i in originals) {
            if (!originals.hasOwnProperty(i)) {
                continue;
            }
            var item = originals[i];
            if (item.id == 'modx-resource-header') {
                item.html = '<h2>' + _('ms2_product_new') + '</h2>';
            }
            else if (item.id == 'modx-resource-tabs') {
                item.stateful = MODx.config['ms2_product_remember_tabs'] == 1;
                item.stateId = 'minishop2-product-' + config.mode + '-tabpanel';
                item.stateEvents = ['tabchange'];
                item.collapsible = false;
                item.getState = function () {
                    return {activeTab: this.items.indexOf(this.getActiveTab())};
                };

                var product = [];
                var other = [];

                for (var i2 in item.items) {
                    if (!item.items.hasOwnProperty(i2)) {
                        continue;
                    }
                    var tab = item.items[i2];
                    switch (tab.id) {
                        case 'modx-resource-settings':
                            tab.items.push(this.getContent(config));
                            product.push(tab);
                            break;
                        case 'modx-page-settings':
                            tab.items = this.getProductSettings(config);
                            product.push(tab);

                            if(miniShop2.config['show_extra'] || miniShop2.config['show_options']) {
                                var copositeOptions;
                                copositeOptions = this.getProductFields(config);
                                if (!miniShop2.config['show_extra']) {
                                    copositeOptions.items = [];
                                }
                                if (miniShop2.config['show_options']) {
                                    var options = this.getProductOptions(config);
                                    if (options) {
                                        copositeOptions.items = copositeOptions.items.concat([{ title: options.title, style: "margin-top:30px;" }],options.items);
                                    }
                                }
                                product.push(copositeOptions);
                            }

                            if (config.mode == 'update' && miniShop2.config['show_links']) {
                                product.push(this.getProductLinks(config));
                            }
                            if (miniShop2.config['show_categories']) {
                                product.push(this.getProductCategories(config));
                            }
                            break;
                        default:
                            other.push(tab);
                    }
                }

                var tabs = [{
                    title: _('ms2_tab_product'),
                    cls: 'panel-wrapper',
                    id: 'minishop2-product-tab',
                    items: [{
                        xtype: 'modx-tabs',
                        id: 'minishop2-product-tabs',
                        stateful: MODx.config['ms2_product_remember_tabs'] == 1,
                        stateId: 'minishop2-product-' + config.mode + '-tabpanel-product',
                        stateEvents: ['tabchange'],
                        getState: function () {
                            return {activeTab: this.items.indexOf(this.getActiveTab())};
                        },
                        deferredRender: false,
                        items: product,
                        resource: config.resource,
                        border: false,
                        listeners: {},
                    }]
                }];

                item.items = tabs.concat(other);
            }
            if (item.id != 'modx-resource-content') {
                fields.push(item);
            }
        }

        return fields;
    },
});

Так же создайте плагин и привяжите его к событию OnDocFormPrerender
<?php
switch ($modx->event->name) {
	case 'OnDocFormPrerender':
	    if($modx->controller->resourceArray['class_key'] == 'msProduct'){
	        if ($miniShop2 = $modx->getService('miniShop2')) {
    	            $modx->controller->addLastJavascript($miniShop2->config['jsUrl'].'mgr/product/product.extends.js');
	        }
	    }
        break;
}

Получится как то так:
Денис
22 ноября 2017, 19:47
2
+1
ТВ поля подключаются после join, так что придется подтянуть всю цепочку вручную:

$projects = $modx->runSnippet('pdoResources',array(
	'parents' => 4,
	'includeTVs' => 'projectCat',
	'loadModels' => 'projects',
	'leftJoin' => '{
		"TvFieldResource" : {
			"class" : "modTemplateVarResource", 
			"on" : "TvFieldResource.contentid = modResource.id" //Связываем тв поле с значением по полю id ресурса
		},
		"TvField" : {
			"class": "modTemplateVar",
			"on": "TvField.id = TvFieldResource.tmplvarid AND TvField.name = \"projectCat\"" //Это связь для тв поля по по имени, хотя можно его и не использовать, а указать в TvFieldResource сразу значение tmplvarid(id тв поля)
		},
		"ProjCats" : {
			"class" : "categories", 
			"on" : "TvFieldResource.value = ProjCats.id" //связываем значение тв поля с вашим классом
		}
	}',
	'select' => '{
		"modResource": "*", //подтягиваем поля ресурса
		"ProjCats": "ProjCats.id as category_id, ProjCats.name as category_name" //и поля вашего класса, создав им псевдонимы category_id и category_name
	}',
    'return' => 'json',
    'showLog' => 1
));

Не проверял, но должно работать.
Александр Мельник
03 ноября 2017, 17:56
3
0
Я делаю так
<div class="sort-title">Сортировать по:</div>
	<div class="sort-item">
	<a href="{$_modx->resource.id | url}?sortby=price&sortdir=DESC">убыванию </a>
	<i class="zmdi zmdi-long-arrow-down"></i>
	</div>
	<div class="sort-item">
	<a href="{$_modx->resource.id | url}?sortby=price&sortdir=ASC">возрастанию</a>
	<i class="zmdi zmdi-long-arrow-up"></i>
	</div>
В вызове сниппета, который будет выводить товары
'sortby' => $_modx->runSnippet('sortItName.php'),
    'sortdir' => $_modx->runSnippet('sortItDir.php'),
Ну и собственно содержание этих сниппетов
sortItDir.php'
<?php
$request=$_GET['sortby'];
switch($request) {
case "price":
    return ("Data.price");
    break;
case "rating":
    return("rating");
    break;
default:
    return("{\"menuindex\":\"DESC\"}");
    break;
}
sortItName.php
<?php
$request=$_GET['sortdir'];
switch($request) {
case "ASC":
    return("ASC");
    break;
case "DESC":
    return("DESC");
    break;
default:
    return("DESC");
    break;
}
Таким образом к ссылкам можно прикреплять любые поля и направления в GET параметрах.
Работает с перезагрузкой страницы, что можно считать минусом. А можно и плюсом, потому что сортировка без перезагрузки приводит к тому, что пагинация перестает работать. Если по умолчанию на странице 20 товаров, отсортировали и скажем товаров стало 10, то изменение пагинации требует сложной (уточню — для меня сложной работы с хешем), а так все ок.