[msOptionsPrice2] - Галерея модификаций.
В msOptionsPrice2 новой версии добавлена галерея модификаций. Это не самостоятельная галерея а лишь работа со стандартной галереей продукта miniShop2

Подключить галерею просто, достаточно указать таб gallery в настройке msoptionsprice_window_modification_tabs
Конечно доступна сортировка изображений модификации.
В модификацию добавлено получение изображений — поле images и превью — поле thumbs.
Указать необходимые для получения превью можно в настройке msoptionsprice_modification_thumbs,
по умолчанию

Теперь теоретически можно менять полностью галерею для каждой модификации продукта.
Надеюсь вам это пригодится.
Новая версия уже доступна в репозитории — modstore.pro/packages/ecommerce/msoptionsprice2
Спасибо за внимание.

Подключить галерею просто, достаточно указать таб gallery в настройке msoptionsprice_window_modification_tabs
modification,gallery
Выводятся все доступные изображения продукта. При наведении на картинку появляется кнопка "+", либо "-" — прикрепить изображение к модификации или открепить.Конечно доступна сортировка изображений модификации.
В модификацию добавлено получение изображений — поле images и превью — поле thumbs.
Указать необходимые для получения превью можно в настройке msoptionsprice_modification_thumbs,
по умолчанию
120x90

Теперь теоретически можно менять полностью галерею для каждой модификации продукта.
Надеюсь вам это пригодится.
Новая версия уже доступна в репозитории — modstore.pro/packages/ecommerce/msoptionsprice2
Спасибо за внимание.
Поблагодарить автора
Отправить деньги
Комментарии: 33
шикардос, например. Спасибо)
пожалуйста!)
Лови 2 плюса, снял одну головную боль.
пасиб!) я чет не думал что галерея так необходима. А судя по + востребована.
эх… эти бы возможности, да полгода назад. Я уже таких костылей наделал…
вот-вот
Володя, Скажи пожалуйста, работает ли компонент с ms2Gallery (вместо стандартной галереи miniShop2 если используется)?
привет. Пока что нет. Но возможность работы с разными галереями заложил.
Будет время доработаю — не все сразу, тем базовый функционал еще не обкатан.
А так да, в планах есть подключения и ms2Gallery и UserFiles. UserFiles к тому же уже умеет заменять стандартную галерею продукта minishop.
Так что это только вопрос времени.
Будет время доработаю — не все сразу, тем базовый функционал еще не обкатан.
А так да, в планах есть подключения и ms2Gallery и UserFiles. UserFiles к тому же уже умеет заменять стандартную галерею продукта minishop.
Так что это только вопрос времени.
Понял, спасибо! И ещё вопрос про совместимость с mFilter2.
К примеру, вывести все цвета товара в фильтре, и при выборе, например, зелёного – картинки поменяются на модификацию в Зелёном варианте) Так можно?
UPD. Или просто вывести все модификации со всеми картинками, и тут уже просто фильтр работае. Оставляет выбранные цвета.
К примеру, вывести все цвета товара в фильтре, и при выборе, например, зелёного – картинки поменяются на модификацию в Зелёном варианте) Так можно?
UPD. Или просто вывести все модификации со всеми картинками, и тут уже просто фильтр работае. Оставляет выбранные цвета.
Понял, спасибо! И ещё вопрос про совместимость с mFilter2.помоему сейчас так и работает. При смене опции в фильтре переключает свойства продукта если они есть.
К примеру, вывести все цвета товара в фильтре, и при выборе, например, зелёного – картинки поменяются на модификацию в Зелёном варианте) Так можно?
Если есть модификация — она будет подгружена. А там уже если у вас фоторама — должен переключить картинку. Если не фоторама — напишите свою обвязку на замену картинок
Можно сюда пример такого вызова mFilter2? Пожалуйста.
вызов mFilter2 самый обычный
вот пример набросал, тут чанк продукта и вызов
gist.github.com/vgrish/78f506cf2fbb940acad3dd9d57ed49cb
вот пример набросал, тут чанк продукта и вызов
gist.github.com/vgrish/78f506cf2fbb940acad3dd9d57ed49cb
Встроенная галерея конечно очень интересная и перспективная доработка, но у неё есть одна абсолютно бессмысленная функция. Из галереи можно выбрать больше одного фото, что меня загнало в смуту. Фото я выбрал несколько и хотел их присвоить к опции, но на деле массив не создаётся и присваивается лишь первое фото.
Очень надеюсь, что возможность присваивать больше одного фото к одной модификации (несколько фото одного цвета с разных сторон) для выбора опции из галереи Fotorama — это вопрос времени :)
Очень надеюсь, что возможность присваивать больше одного фото к одной модификации (несколько фото одного цвета с разных сторон) для выбора опции из галереи Fotorama — это вопрос времени :)
хотя стоп… В процессинге браузера я вижу 2-е картинки…
Плейсхолдер Images нужно использовать?
Плейсхолдер Images нужно использовать?
Плейсхолдер Images нужно использовать?для сниппета msOptionsPrice.modification вообще не было вывода. Добавил, обновите компонент — плейсхолдер thumbs с массивом картинок
Подскажите как вывести с помощью msOptionsPrice.modification
ссылку на оригинальную картинку (из которой нарезаются превьюшки) к каждой модификации
ссылку на оригинальную картинку (из которой нарезаются превьюшки) к каждой модификации
задайте пустой tpl и посмотрите какие плейсхолдеры достпны.
Если я не ошибаюсь то основная картинка в thumbs -> main
Если я не ошибаюсь то основная картинка в thumbs -> main
в параметрах сниппета писал &includeThumbs=`main,small`
вывод в шаблоне {$_pls['main']} ничего не выводит
вывод в шаблоне {$_pls['small']} выводит превьюшку у каждой модификации
видимо как-то не так вызываю
вывод в шаблоне {$_pls['main']} ничего не выводит
вывод в шаблоне {$_pls['small']} выводит превьюшку у каждой модификации
видимо как-то не так вызываю
Пишите в ТП с указанием доступов к админке и ссылкой на чанк вызова.
Спасибо.
Спасибо.
Здравствуйте! Тестирую дополнение на тестовом сайте. Изображение модификации при выборе другого цвета не переключается
s11353.h9.modhost.pro/index.php?id=4
скажите, пожалуйста, в чем может быть причина?
спасибо
s11353.h9.modhost.pro/index.php?id=4
скажите, пожалуйста, в чем может быть причина?
спасибо
не заметил
В чанк галереи необходимо добавить идентификаторыразобрался
data-rid="{$file['product_id']}" data-iid="{$file['id']}"
Другой вопрос. Нельзя ли сделать чтобы для выбранной модификации выводились только фото данной модификации? А то при пролистывании фото, отображаются фото из другой модификации. Пример s11353.h9.modhost.pro/index.php?id=5
Изображения модификации лежат в поле thumbs.
Можно, по событию загрузки модификации создавать галерею с изображениями данной модификации.
Можно, по событию загрузки модификации создавать галерею с изображениями данной модификации.
Спасибо за ответ, но к сожалению не представляю как это сделать. Не могли бы набросать где что прописывать?
Пожалуйста.
Не могли бы набросать где что прописывать?готового примера к сожалению нет…
Добрый день. Сейчас этот функционал поддерживается? Делаю по заметке, но галерея не меняется. Хотя в админке вкладка «галерея» и выбор фото доступны.
Работает данный функционал, где-то месяц назад использовал на одном из сайтов. Нужно попотеть, чтобы завести его))
Можно подробнее — куда смотреть, что доработать нужно? Настройками из коробки не обойтись?
Вносил изменение в js тот который в настройках есть ([[+assetsUrl]]js/web/default2.js)
Вот он:
Вот он:
/* 2.4.6 */
(function (window, document, $, msOptionsPriceConfig) {
var msOptionsPrice = msOptionsPrice || {};
msOptionsPrice.options = {
errorClass: "error",
errorElement: "span",
showSpinner: true,
};
msOptionsPrice.setup = function () {
msOptionsPrice.$doc = $(document);
msOptionsPrice.$body = $('body');
msOptionsPrice.$spinner = null;
msOptionsPrice.Product.parent = '#msProduct';
msOptionsPrice.Product.form = '.ms2_form.msoptionsprice-product';
msOptionsPrice.Product.modification = '.ms2_form.msoptionsprice-modification';
msOptionsPrice.Product.cost = '.msoptionsprice-cost';
msOptionsPrice.Product.old_cost = '.msoptionsprice-old-cost';
msOptionsPrice.Product.price = '.msoptionsprice-old-price';
msOptionsPrice.Product.mass = '.msoptionsprice-mass';
msOptionsPrice.Product.article = '.msoptionsprice-article';
msOptionsPrice.Product.weight = '.msoptionsprice-weight';
msOptionsPrice.Product.count = '.msoptionsprice-count';
msOptionsPrice.Product.name = '.msoptionsprice-name';
msOptionsPrice.Product.msbonus = '.msoptionsprice-msbonus';
msOptionsPrice.Product.gallery = '.msoptionsprice-gallery';
msOptionsPrice.Product.fotorama = '.fotorama';
msOptionsPrice.Product.image = '.msoptionsprice-image';
msOptionsPrice.Product.prefix = '.msoptionsprice-';
msOptionsPrice.exclude = {};
msOptionsPrice.exclude.fieldNames = ['count'];
msOptionsPrice.exclude.fieldClasess = ['msal_input'];
msOptionsPrice.Product.msal_price = '#msal_price_original';
msOptionsPrice.Product.inputParent = '.input-parent';
msOptionsPrice.timeout = 300;
};
msOptionsPrice.initialize = function () {
msOptionsPrice.setup();
msOptionsPrice.miniShop2.initialize();
/* get modification on change options */
msOptionsPrice.$doc.on('change', msOptionsPrice.Product.form, function (e) {
if (msOptionsPrice.Tools.inArray(e.target.name, msOptionsPrice.exclude.fieldNames)) {
console.info('[msOptionsPrice] Exclude field "' + e.target.name + '"');
return false;
}
for (i in msOptionsPrice.exclude.fieldClasess) {
if (!msOptionsPrice.exclude.fieldClasess.hasOwnProperty(i)) {
continue;
}
var cls = msOptionsPrice.exclude.fieldClasess[i];
if ($(e.target).hasClass(cls)) {
console.info('[msOptionsPrice] Exclude field "' + e.target.name + '"');
return false;
}
}
msOptionsPrice.Product.processOptions(this);
setTimeout((function () {
msOptionsPrice.Product.action('modification/get', this);
}.bind(this)), msOptionsPrice.timeout);
e.preventDefault();
return false;
});
/* get modification on document ready */
msOptionsPrice.$doc.ready(function () {
msOptionsPrice.mSearch2.setOptionsByFilter();
$(msOptionsPrice.Product.form).each(function () {
$(this).trigger('change');
/*
msOptionsPrice.Product.action('modification/get', this);
*/
});
});
/* get modification on change image */
msOptionsPrice.$doc.on('fotorama:show', msOptionsPrice.Product.gallery + ' ' + msOptionsPrice.Product.fotorama, function (e, fotorama, extra) {
var item, form;
item = fotorama.activeFrame;
if (extra.user && item.rid && item.iid) {
// form = $(e.target).closest(msOptionsPrice.Product.parent).find(msOptionsPrice.Product.form);
form = $(e.target).closest(msOptionsPrice.Product.form);
if (!form.length) {
form = $(msOptionsPrice.Product.cost + msOptionsPrice.Product.prefix + item.rid)
.closest(msOptionsPrice.Product.form);
}
if (form.length) {
msOptionsPrice.Product.action('modification/get', form, {id: item.rid, iid: item.iid});
}
}
});
/* set rid, iid image */
msOptionsPrice.$doc.on('fotorama:load', msOptionsPrice.Product.gallery + ' ' + msOptionsPrice.Product.fotorama, function (e, fotorama, extra) {
fotorama.data.filter(function (item, r) {
if (item.rid && item.iid && item.thumb) {
var thumb = $(this).find('img[src$="' + item.thumb + '"]');
if (thumb) {
thumb
.data('i', item.i)
.attr('data-i', item.i)
.data('rid', item.rid)
.attr('data-rid', item.rid)
.data('iid', item.rid)
.attr('data-iid', item.iid);
}
if (fotorama.activeFrame.i == item.i) {
//var form = $(e.target).closest(msOptionsPrice.Product.parent).find(msOptionsPrice.Product.form);
form = $(e.target).closest(msOptionsPrice.Product.form);
if (!form.length) {
form = $(msOptionsPrice.Product.cost + msOptionsPrice.Product.prefix + item.rid)
.closest(msOptionsPrice.Product.form);
}
if (form.length) {
msOptionsPrice.Product.action('modification/get', form, {id: item.rid, iid: item.iid});
}
}
}
}, this);
});
/* set options and get modification on "mse2_load" */
msOptionsPrice.$doc.on('mse2_load', function (e, response) {
msOptionsPrice.mSearch2.setOptionsByFilter();
$(msOptionsPrice.Product.form).each(function () {
$(this).trigger('change');
/*
msOptionsPrice.Product.action('modification/get', this);
*/
});
});
/* get modification on "pdopage_load" */
msOptionsPrice.$doc.on('pdopage_load', function (e, response) {
$(msOptionsPrice.Product.form).each(function () {
$(this).trigger('change');
});
});
/* set options and get modification on "modification" click */
msOptionsPrice.$doc.on('click touchend', msOptionsPrice.Product.modification, function (e) {
if (!$(e.target).is(":submit")) {
msOptionsPrice.Product.action('modification/set', this);
}
});
};
msOptionsPrice.mSearch2 = {
setOptionsByFilter: function () {
/* if mse2Config set options */
if (typeof(mse2Config) != 'undefined' && mSearch2.initialized) {
var filterDelimeter = mse2Config.filter_delimeter || '|';
var valuesDelimeter = mse2Config.values_delimeter || ',';
var aliases = mse2Config.aliases || {};
var filters = mSearch2.getFilters();
for (i in filters) {
if (!filters.hasOwnProperty(i)) {
continue;
}
var filterName = String(i);
var filterValue = String(filters[i]).split(valuesDelimeter);
if (typeof(aliases[filterName]) != 'undefined') {
filterName = aliases[filterName];
}
filterName = String(filterName).split(filterDelimeter);
switch (filterName[0]) {
case 'msoption':
msOptionsPrice.Tools.setOptionValue(filterName[1], filterValue);
break;
}
}
}
},
};
msOptionsPrice.miniShop2 = {
initialize: function () {
if (typeof(miniShop2) == 'undefined') {
//console.log('[msOptionsPrice:Error] Initialization Error. msOptionsPrice required');
//return false;
}
if (msOptionsPriceConfig.allow_remains) {
miniShop2.Callbacks.add('Cart.change.response.error', 'msoptionsprice', function (response) {
var count = miniShop2.sendData.$form.find(miniShop2.Cart.countInput);
count.val(count.attr('value'));
});
miniShop2.Callbacks.add('Cart.change.response.success', 'msoptionsprice', function (response) {
var count = miniShop2.sendData.$form.find(miniShop2.Cart.countInput);
count.removeClass(msOptionsPrice.options.errorClass);
});
miniShop2.Callbacks.add('Order.submit.before', 'msoptionsprice', function () {
var result = msOptionsPrice.Order.action('order/check', miniShop2.sendData.$form);
if (!result) {
$(':button, a', miniShop2.Order.order).attr('disabled', false).prop('disabled', false);
}
return result;
});
}
},
};
msOptionsPrice.Order = {
action: function (action, form, data) {
var formData = new FormData($(form)[0]);
if (!msOptionsPrice.Tools.empty(data)) {
for (key in data) {
if (!data.hasOwnProperty(key)) {
continue;
}
formData.append(key, data[key]);
}
}
formData.append('action', action);
formData.append('ctx', msOptionsPriceConfig.ctx);
var request = $.ajax({
type: 'POST',
url: msOptionsPriceConfig.actionUrl,
dataType: 'json',
data: formData,
async: false,
cache: false,
contentType: false,
processData: false,
beforeSend: function () {
msOptionsPrice.Spinner.show();
return true;
},
success: function (response) {
msOptionsPrice.Spinner.hide();
msOptionsPrice.$doc.trigger('msoptionsprice_order_action', [action, form, response]);
var data = response.data;
var errors = [];
if (!msOptionsPrice.Tools.empty(data.errors)) {
errors.push(data.errors);
}
if (!response.success) {
if (!msOptionsPrice.Tools.empty(response.message)) {
miniShop2.Message.error(response.message);
}
if (!msOptionsPrice.Tools.empty(data.required)) {
for (var key in data.required) {
if (!data.required.hasOwnProperty(key)) {
continue;
}
var pls = data.required[key];
var item = $('#' + key);
var count = item.find(miniShop2.Cart.countInput);
count.addClass(msOptionsPrice.options.errorClass);
var f = count.closest('form');
var err = item.find(msOptionsPrice.options.errorElement + '.' + msOptionsPrice.options.errorClass);
if (err.length < 1) {
err = $("<" + msOptionsPrice.options.errorElement + "/>").appendTo(f.parent())
.addClass(msOptionsPrice.options.errorClass);
}
err.text(pls['message']).show();
}
}
}
else {
if (!msOptionsPrice.Tools.empty(data.cart)) {
for (var key in data.cart) {
if (!data.cart.hasOwnProperty(key)) {
continue;
}
var pls = data.cart[key];
var item = $('#' + key);
if (item.length < 1) {
continue;
}
var count = item.find(miniShop2.Cart.countInput);
count.removeClass(msOptionsPrice.options.errorClass);
var err = item.find(msOptionsPrice.options.errorElement + '.' + msOptionsPrice.options.errorClass);
err.text('').hide();
}
}
}
if (!msOptionsPrice.Tools.empty(errors)) {
console.log(errors.join('
'));
}
}
}).done(function (response) {
}).fail(function (jqXHR, textStatus, errorThrown) {
});
if (!!request.responseJSON) {
msOptionsPrice.Spinner.hide();
return request.responseJSON.success || false;
}
return true;
}
};
msOptionsPrice.Product = {
action: function (action, form, data) {
var formData = new FormData($(form)[0]);
if (!msOptionsPrice.Tools.empty(data)) {
for (key in data) {
if (!data.hasOwnProperty(key)) {
continue;
}
formData.append(key, data[key]);
}
}
formData.append('action', action);
formData.append('ctx', msOptionsPriceConfig.ctx);
$.ajax({
type: 'POST',
url: msOptionsPriceConfig.actionUrl,
dataType: 'json',
data: formData,
async: true,
cache: false,
contentType: false,
processData: false,
beforeSend: function () {
msOptionsPrice.Spinner.show();
msOptionsPrice.Product.submitDisabled($(form)[0]);
return true;
},
success: function (response) {
msOptionsPrice.Spinner.hide();
msOptionsPrice.Product.submitEnabled($(form)[0]);
msOptionsPrice.$doc.trigger('msoptionsprice_product_action', [action, form, response]);
if (response.success && response.data) {
var data = response.data;
var errors = [];
var html;
if (!msOptionsPrice.Tools.empty(data.errors)) {
errors.push(data.errors);
}
if (!msOptionsPrice.Tools.empty(data.modification)) {
['name', 'article', 'count', 'weight', 'cost', 'old_cost', 'price', 'mass', 'msbonus'].filter(function (key) {
if (msOptionsPrice.Product[key]) {
var value = data.modification[key];
switch (key) {
case 'old_cost':
if (data.modification[key] == data.modification['cost']) {
value = 0;
}
break;
default:
break;
}
if (msOptionsPrice.Tools.empty(value) && !msOptionsPriceConfig['allow_zero_' + key]) {
return true;
}
msOptionsPrice.Tools.setValue(null, value, key, data.rid);
}
});
key = 'description';
html = $(msOptionsPrice.Product.prefix + data.rid + msOptionsPrice.Product.prefix + key);
if (html.length > 0) {
html.html(data.modification[key] || "");
}
}
/* set modification/set */
var msoptionsprice_mid = $(msOptionsPrice.Product.prefix + data.rid).closest(msOptionsPrice.Product.form).find('input[name="mid"]');
if (msoptionsprice_mid.length) {
if (action == 'modification/set') {
msoptionsprice_mid.val(data.modification.id);
}
if (action == 'modification/get') {
msoptionsprice_mid.val(data.modification.id);
}
}
/* set image */
if (miniShop2.Gallery && !msOptionsPrice.Tools.empty(data.modification.images) && msOptionsPrice.Tools.empty(data.set.options)) {
$('.fotorama').on('fotorama:load', function (e, fotorama, extra) {
if (extra && extra.frame && extra.frame.iid == data.modification.images[0]) {
msOptionsPrice.Tools.setGalleryImage(extra.frame.rid, extra.frame.iid);
}
});
msOptionsPrice.Tools.setGalleryImage(data.rid, data.modification.images[0]);
} else if (miniShop2.Gallery && !msOptionsPrice.Tools.empty(data.modification.images) && !msOptionsPrice.Tools.empty(data.set.image)) {
msOptionsPrice.Tools.setGalleryImage(data.rid, data.modification.images[0]);
}
/* set options */
var set = !msOptionsPrice.Tools.empty(data.set.options);
/* set msal */
var msal = data.options['msal'];
if (!set && !msOptionsPrice.Tools.empty(msal)) {
data.options = {
'msal': msal
};
set = true;
}
if (set) {
for (var key in data.options) {
if (!data.options.hasOwnProperty(key)) {
continue;
}
var value = data.options[key];
if (typeof value === "object") {
for (idx in value) {
var _key = [key, idx];
var _value = value[idx];
_value = msOptionsPrice.Tools.formatOptionValue(key, _value);
msOptionsPrice.Tools.setOptionValue(_key, _value, data.rid);
}
}
else {
value = msOptionsPrice.Tools.formatOptionValue(key, value);
msOptionsPrice.Tools.setOptionValue(key, value, data.rid);
}
}
}
// html
for (var key in data.options) {
if (!data.options.hasOwnProperty(key)) {
continue;
}
html = $(msOptionsPrice.Product.prefix + data.rid + msOptionsPrice.Product.prefix + key);
if (html.length > 0) {
html.html(data.options[key]);
}
}
if (!msOptionsPrice.Tools.empty(errors)) {
console.log(errors.join('
'));
}
}
else if (!response.success) {
}
}
}).done(function (response) {
}).fail(function (jqXHR, textStatus, errorThrown) {
msOptionsPrice.Spinner.hide();
msOptionsPrice.Product.submitEnabled($(form)[0]);
});
},
processOptions: function (form) {
var $form = $(form),
$constraints,
$related,
$enabled = [],
$disabled = [],
constraints,
options = {},
selector = 'input, option';
$constraints = $form.find("[data-constraints]");
$related = $form.find("[data-constraints]").find(selector);
constraints = $constraints.map(function () {
return $(this).data('constraints');
});
constraints = $.grep(constraints, function (v, k) {
return $.inArray(v, constraints) === k;
});
constraints.sort();
constraints.filter(function (key) {
var value = msOptionsPrice.Tools.getOptionValue(key, form);
if (typeof (value) != 'undefined') {
options[key] = value;
}
return true;
});
if (options.length < 1) {
return;
}
$related.filter(function () {
var $curr = $(this);
switch (this.tagName) {
case 'OPTION':
$curr = $curr.parent('select');
break;
}
var opts = [];
var currConstraints = $curr.data('constraints') || $curr.closest('[data-constraints]').data('constraints') || [];
currConstraints.filter(function (key) {
if (options.hasOwnProperty(key)) {
opts.push('' + key + '=' + msOptionsPrice.Tools.escapedValue(options[key]) + '');
//opts.push('' + key + '=' + options[key] + '');
//opts.push('"'+key+'='+options[key]+'"');
}
});
opts.sort();
/* opts = opts.join('(.*?)');
opts = msOptionsPrice.Tools.escapedValue(opts);
opts = new RegExp(opts);*/
opts = opts.join('([^\"]+)');
opts = new RegExp(opts+'([\&\"])');
if (this.dataset.relations && msOptionsPrice.Tools.escapedValue(this.dataset.relations).match(opts)) {
$enabled.push(this);
}
else {
$disabled.push(this);
}
return true;
});
$enabled = $($enabled).map(function (i, self) {
return self;
});
$disabled = $($disabled).map(function (i, self) {
return self;
});
$enabled.attr('disabled', false).prop('disabled', false);
$disabled.attr('disabled', true).prop('disabled', true);
$enabled.closest(msOptionsPrice.Product.inputParent).show();
$disabled.closest(msOptionsPrice.Product.inputParent).hide();
$constraints.map(function () {
var $fields = $(this).find(selector);
if ($fields.length < 1) {
return true;
}
switch ($fields[0].tagName) {
case 'INPUT':
if ($fields.filter(':not(:disabled):checked').length < 1) {
$fields.filter(':not(:disabled):first').prop('checked', true);
}
break;
case 'OPTION':
if ($fields.filter(':not(:disabled):checked:selected').length < 1) {
$fields.filter(':not(:disabled):first').prop('checked', true).prop('selected', true);
}
break;
}
});
},
submitDisabled: function (form) {
$(form).find(':button[value="cart/add"], a[value="cart/add"]').attr('disabled', true).prop('disabled', true);
},
submitEnabled: function (form) {
$(form).find(':button[value="cart/add"], a[value="cart/add"]').attr('disabled', false).prop('disabled', false);
},
};
msOptionsPrice.Tools = {
escapedValue: function (value) {
return value
.replace(new RegExp("\\^", "g"), '{v}')
.replace(new RegExp("\\$", "g"), '{s}')
.replace(new RegExp('\\*', "g"), '{z}')
.replace(new RegExp('\\+', "g"), '{p}');
},
arrayIntersect: function (array1, array2) {
var result = array1.filter(function (n) {
return array2.indexOf(n) !== -1;
});
return result;
},
inArray: function (needle, haystack) {
for (key in haystack) {
if (haystack[key] == needle) return true;
}
return false;
},
empty: function (value) {
return (typeof(value) == 'undefined' || value == 0 || value === null || value === false || (typeof(value) == 'string' && value.replace(/\s+/g, '') == '') || (typeof(value) == 'object' && value.length == 0));
},
setValue: function (self, value, key, rid) {
var $this = null;
if (self) {
$this = $(self);
}
else if (key && rid) {
$this = $(msOptionsPrice.Product[key] + msOptionsPrice.Product.prefix + rid);
}
if (!$this.length && !rid) {
$this = $(msOptionsPrice.Product[key]);
}
if (!$this.length) {
return;
}
var tagName = $this[0].tagName;
var tagType = $this[0].type;
switch (true) {
case tagName == 'INPUT' && (key instanceof Array) && msOptionsPrice.Tools.inArray('msal', key):
$this.val(value).trigger('change');
break;
case tagName == 'INPUT' && tagType == 'checkbox':
if (!(value instanceof Array)) {
value = [value];
}
if (msOptionsPrice.Tools.inArray($this.val(), value)) {
$this.prop('checked', true);
}
else {
$this.prop('checked', false);
}
break;
case tagName == 'INPUT' && tagType != 'radio':
$this.val(value);
break;
case tagName == 'INPUT' && tagType == 'radio':
if (!(value instanceof Array)) {
value = [value];
}
value.filter(function (item, r) {
if ($this.val() == item) {
$this.prop('checked', true);
}
else {
$this.prop('checked', false);
}
}, this);
break;
case tagName == 'SELECT':
if (!(value instanceof Array)) {
value = [value];
}
value.filter(function (item, r) {
if ($this.find('option[value="' + item + '"]').length) {
$this.val([item]);
}
}, this);
break;
default:
switch (true) {
case key == 'cost':
/* refresh msal price */
msOptionsPrice.Tools.setValue(null, value, 'msal_price', rid);
break;
case key == 'old_cost' && msOptionsPrice.Tools.empty(value):
/* hide empty old_cost */
$this.parent().hide();
break;
case key == 'old_cost' && !msOptionsPrice.Tools.empty(value):
/* show not empty old_cost */
$this.parent().show();
break;
}
value = msOptionsPrice.Tools.formatOptionValue(key, value);
$this.html(value);
break;
}
return;
},
getOptionName: function (key) {
var name = 'options';
if (!(key instanceof Array)) {
key = [key];
}
key.filter(function (i) {
name += '[' + i + ']';
});
return name.toString();
},
getOptionValue: function (key, form) {
var value;
var name = msOptionsPrice.Tools.getOptionName(key);
var $field = $(form).find('[name="' + name + '"]');
if ($field.length > 0) {
switch ($field[0].tagName) {
case 'INPUT':
value = $field.filter(':checked').val();
break;
case 'SELECT':
value = $field.val();
break;
}
}
return value;
},
setOptionValue: function (key, value, rid) {
var inputs;
var name = msOptionsPrice.Tools.getOptionName(key);
if (rid) {
inputs = $(msOptionsPrice.Product.cost + msOptionsPrice.Product.prefix + rid)
.closest(msOptionsPrice.Product.form)
.find('[name="' + name + '"]');
}
else {
inputs = $(msOptionsPrice.Product.cost)
.closest(msOptionsPrice.Product.form)
.find('[name="' + name + '"]');
}
if (inputs) {
inputs.each(function () {
msOptionsPrice.Tools.setValue(this, value, key);
});
}
return;
},
setGalleryImage: function (rid, iid) {
var fotorama = $('.fotorama__img[data-rid="' + rid + '"]').closest(msOptionsPrice.Product.gallery).find('.fotorama').data('fotorama');
if (!!fotorama) {
if (fotorama.activeFrame['iid'] == iid) {
return;
}
fotorama.data.filter(function (item, r) {
if (item['iid'] == iid) {
fotorama.show(item['i'] - 1);
}
}, this);
}
},
/*
formatOptionValue: function (key, value) {
switch (key) {
case 'cost':
case 'old_cost':
case 'price':
case 'old_price':
if (typeof miniShop2?.Utils?.formatPrice === 'function') {
value = miniShop2.Utils.formatPrice(value);
}
break;
case 'mass':
case 'weight':
//if (miniShop2 && miniShop2.Utils.formatWeight) {
// value = miniShop2.Utils.formatWeight(value);
//}
break;
default:
break;
}
return value;
},
*/
formatOptionValue: function (key, value) {
switch (key) {
case 'cost':
case 'old_cost':
case 'price':
case 'old_price':
value = this.formatPrice(value); // Используем свою функцию formatPrice
break;
case 'mass':
case 'weight':
if (typeof miniShop2?.Utils?.formatWeight === 'function') {
value = miniShop2.Utils.formatWeight(value);
}
break;
default:
break;
}
return value;
},
formatPrice: function (value) {
// Форматируем число, добавляя пробелы в качестве разделителей тысяч.
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
},
/* TODO remove */
setInputValue: function (key, value, rid) {
var inputs;
if (rid) {
inputs = $(msOptionsPrice.Product.cost + msOptionsPrice.Product.prefix + rid)
.closest(msOptionsPrice.Product.form)
.find('[name="options[' + key + ']"]');
}
else {
inputs = $(msOptionsPrice.Product.cost)
.closest(msOptionsPrice.Product.form)
.find('[name="options[' + key + ']"]');
}
if (!inputs) {
return false;
}
inputs.each(function () {
msOptionsPrice.Tools.setValue(this, value);
});
},
};
msOptionsPrice.Spinner = {
create: function () {
return $('<div class="msoptionsprice-spinner"></div>');
},
show: function () {
if (!msOptionsPrice.options.showSpinner) {
return;
}
msOptionsPrice.$spinner = msOptionsPrice.$spinner || this.create();
msOptionsPrice.$body.append(msOptionsPrice.$spinner);
return msOptionsPrice.$spinner.show();
},
hide: function () {
if (msOptionsPrice.$spinner) {
return msOptionsPrice.$spinner.remove();
}
},
};
$(document).ready(function ($) {
});
msOptionsPrice.initialize();
window.msOptionsPrice = msOptionsPrice;
})(window, document, jQuery, msOptionsPriceConfig);
/* event example */
/*$(document).on('msoptionsprice_product_action', function (e, action, form, response) {
//console.log(action, form, response);
});*/
/*
reload gallery
$(document).on('msoptionsprice_product_action', function (e, action, form, r) {
if (action == 'modification/get' && r.success && r.data) {
var m = r.data.modification || {};
var thumbs = m.thumbs || {main:['default.png']};
var fotorama = $(form).closest('#msProduct').find('.fotorama').data('fotorama');
if (fotorama) {
var images = [];
(thumbs.main || []).filter(function (href) {
images.push({img: href, caption: ''})
});
}
}
});*/
Вот пример как вызываю
<form class="ms2_form msoptionsprice-product space-y-2" method="post">
<input type="hidden" name="id" value="[[*id]]">
<input type="hidden" name="count" id="product_price" value="1"/>
<input type="hidden" name="options" value="[]">
[[!msOptionsPrice.option?
&options=`palitra2,verhetaz2,futerovka2,vidkamen2,kamenkrishka2,radiussteklo2,povorotmeh2,maternoga2,raspol_pech2,vidkamepanel2,kamenkrishka3,maternoga3`
&sortOptions=`
vidkamepanel2:SORT_ASC:SORT_STRING,
raspol_pech2:SORT_ASC:SORT_STRING,
maternoga2:SORT_ASC:SORT_STRING,
maternoga3:SORT_ASC:SORT_STRING,
povorotmeh2:SORT_ASC:SORT_STRING,
radiussteklo2:SORT_ASC:SORT_STRING,
kamenkrishka2:SORT_ASC:SORT_STRING,
kamenkrishka3:SORT_ASC:SORT_STRING,
vidkamen2:SORT_ASC:SORT_STRING,
palitra2:SORT_ASC:SORT_STRING,
futerovka2:SORT_ASC:SORT_STRING,
verhetaz2:SORT_DESC:SORT_STRING,
`
&tpl=`zbagira.tpl.msOptions.radio`
&constraintOptions=`{"vidkamen2":["maternoga2"],"kamenkrishka2":["maternoga2"],
"maternoga3":["vidkamepanel2","kamenkrishka3"],
"kamenkrishka3":["vidkamepanel2"],
"vidkamepanel2":["maternoga3"],
"maternoga3":["kamenkrishka3"]
}`
]]
<div id="my-image-container" class="w-full button--icons"></div>
<button type="submit" class="w-full button button--primary button--icons" name="ms2_action" value="cart/add">
<span>В корзину</span>
<svg class="size-5">
<use xlink:href="/assets/components/zbagira/tema/images/template/icons.svg#cart"></use>
</svg>
</button>
</form>
zbagira.tpl.msOptions.radio{foreach $options as $name => $values}
<div class="sm-text "><b>{('ms2_product_' ~ $name) | lexicon}</b></div>
<div class="flex flex-wrap gap-2"
{if $constraints[$name]}
data-constraints="{$constraints[$name]| json_encode: 256 | htmlentities}"
{/if}
>
{foreach $values as $value index=$index}
<label class="input-parent flex items-center gap-3 p-2 duration-200 border border-neutral-200 rounded-xl hover:border-neutral-400">
<input type="radio" class="pointer-events-none form-radio" value="{$values[$index]}" name="options[{$name}]" {if $index == 0}checked="checked"{/if}
{if $constraints[$name]}
data-relations="{$relations[$name][$value]| json_encode: 256 | htmlentities}"
{/if}
/>
<div class="text-sm text-neutral-900">{$values[$index]|replace:'0_':''}</div>
</label>
{/foreach}
</div>
{/foreach}
Пока не зводится( Скрипт заменил, но все так же подменяет по одной фотке, а гелерею целиком не тянет. Спасибо, что уделили время! Будем дальше думать
А целую галерею) я не так понял, думал одну фотку менять, у меня из коробки и одна не менялась (фотораму не использую на сайте) два часа возился. Как целую галерею менять подсказать не могу не использовал ни когда.
По одной фотке тоже не менялось. Баг какой-то, похоже. В ТП Володя помог. А вот по этой заметке хотелось бы менять группу фото, но это уже не работает(
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.