[msOptionsPrice2] - Галерея модификаций.

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



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

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


Теперь теоретически можно менять полностью галерею для каждой модификации продукта.
Надеюсь вам это пригодится.
Новая версия уже доступна в репозитории — modstore.pro/packages/ecommerce/msoptionsprice2
Спасибо за внимание.
Володя
18 ноября 2016, 13:31
modx.pro
3
8 094
+23
Поблагодарить автора Отправить деньги

Комментарии: 33

mngatoff
18 ноября 2016, 16:40
+3
шикардос, например. Спасибо)
    Володя
    19 ноября 2016, 10:22
    +5
    пожалуйста!)
      Антон
      Антон
      19 ноября 2016, 20:27
      +2
      Лови 2 плюса, снял одну головную боль.
        Володя
        20 ноября 2016, 17:23
        +2
        пасиб!) я чет не думал что галерея так необходима. А судя по + востребована.
    Дмитрий
    18 ноября 2016, 19:23
    +3
    эх… эти бы возможности, да полгода назад. Я уже таких костылей наделал…
      mngatoff
      21 ноября 2016, 00:42
      0
      вот-вот
      Klike
      23 ноября 2016, 10:39
      +1
      Володя, Скажи пожалуйста, работает ли компонент с ms2Gallery (вместо стандартной галереи miniShop2 если используется)?
        Володя
        23 ноября 2016, 11:20
        +1
        привет. Пока что нет. Но возможность работы с разными галереями заложил.
        Будет время доработаю — не все сразу, тем базовый функционал еще не обкатан.
        А так да, в планах есть подключения и ms2Gallery и UserFiles. UserFiles к тому же уже умеет заменять стандартную галерею продукта minishop.
        Так что это только вопрос времени.
          Klike
          23 ноября 2016, 11:47
          1
          0
          Понял, спасибо! И ещё вопрос про совместимость с mFilter2.
          К примеру, вывести все цвета товара в фильтре, и при выборе, например, зелёного – картинки поменяются на модификацию в Зелёном варианте) Так можно?

          UPD. Или просто вывести все модификации со всеми картинками, и тут уже просто фильтр работае. Оставляет выбранные цвета.
            Володя
            23 ноября 2016, 14:19
            0
            Понял, спасибо! И ещё вопрос про совместимость с mFilter2.
            К примеру, вывести все цвета товара в фильтре, и при выборе, например, зелёного – картинки поменяются на модификацию в Зелёном варианте) Так можно?
            помоему сейчас так и работает. При смене опции в фильтре переключает свойства продукта если они есть.
            Если есть модификация — она будет подгружена. А там уже если у вас фоторама — должен переключить картинку. Если не фоторама — напишите свою обвязку на замену картинок
              Антон
              Антон
              23 ноября 2016, 19:50
              0
              Можно сюда пример такого вызова mFilter2? Пожалуйста.
      Алексей
      22 мая 2017, 01:38
      0
      Встроенная галерея конечно очень интересная и перспективная доработка, но у неё есть одна абсолютно бессмысленная функция. Из галереи можно выбрать больше одного фото, что меня загнало в смуту. Фото я выбрал несколько и хотел их присвоить к опции, но на деле массив не создаётся и присваивается лишь первое фото.

      Очень надеюсь, что возможность присваивать больше одного фото к одной модификации (несколько фото одного цвета с разных сторон) для выбора опции из галереи Fotorama — это вопрос времени :)
        Алексей
        22 мая 2017, 02:07
        0
        хотя стоп… В процессинге браузера я вижу 2-е картинки…

        Плейсхолдер Images нужно использовать?
          Володя
          22 мая 2017, 10:27
          0
          Плейсхолдер Images нужно использовать?
          для сниппета msOptionsPrice.modification вообще не было вывода. Добавил, обновите компонент — плейсхолдер thumbs с массивом картинок
            Юрий Венедиктович
            08 августа 2017, 21:18
            0
            Подскажите как вывести с помощью msOptionsPrice.modification
            ссылку на оригинальную картинку (из которой нарезаются превьюшки) к каждой модификации

              Володя
              09 августа 2017, 09:42
              0
              задайте пустой tpl и посмотрите какие плейсхолдеры достпны.
              Если я не ошибаюсь то основная картинка в thumbs -> main
                Юрий Венедиктович
                09 августа 2017, 12:12
                0
                в параметрах сниппета писал &includeThumbs=`main,small`
                вывод в шаблоне {$_pls['main']} ничего не выводит
                вывод в шаблоне {$_pls['small']} выводит превьюшку у каждой модификации
                видимо как-то не так вызываю
                  Володя
                  09 августа 2017, 12:15
                  0
                  Пишите в ТП с указанием доступов к админке и ссылкой на чанк вызова.
                  Спасибо.
        Надир
        14 октября 2017, 21:52
        0
        Здравствуйте! Тестирую дополнение на тестовом сайте. Изображение модификации при выборе другого цвета не переключается
        s11353.h9.modhost.pro/index.php?id=4

        скажите, пожалуйста, в чем может быть причина?

        спасибо
          Надир
          14 октября 2017, 22:02
          0
          не заметил
          В чанк галереи необходимо добавить идентификаторы
          data-rid="{$file['product_id']}" data-iid="{$file['id']}"
          разобрался
          Надир
          14 октября 2017, 22:37
          0
          Другой вопрос. Нельзя ли сделать чтобы для выбранной модификации выводились только фото данной модификации? А то при пролистывании фото, отображаются фото из другой модификации. Пример s11353.h9.modhost.pro/index.php?id=5
            Володя
            15 октября 2017, 10:09
            0
            Изображения модификации лежат в поле thumbs.
            Можно, по событию загрузки модификации создавать галерею с изображениями данной модификации.
              Надир
              15 октября 2017, 11:11
              0
              Спасибо за ответ, но к сожалению не представляю как это сделать. Не могли бы набросать где что прописывать?
                Володя
                15 октября 2017, 13:18
                0
                Пожалуйста.
                Не могли бы набросать где что прописывать?
                готового примера к сожалению нет…
            Виктор
            01 мая 2025, 11:54
            0
            Добрый день. Сейчас этот функционал поддерживается? Делаю по заметке, но галерея не меняется. Хотя в админке вкладка «галерея» и выбор фото доступны.
              Ivan K.
              01 мая 2025, 18:18
              0
              Работает данный функционал, где-то месяц назад использовал на одном из сайтов. Нужно попотеть, чтобы завести его))
                Виктор
                02 мая 2025, 11:45
                0
                Можно подробнее — куда смотреть, что доработать нужно? Настройками из коробки не обойтись?
                  Ivan K.
                  02 мая 2025, 12:03
                  0
                  Вносил изменение в 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: ''})
                              });
                          }
                      }
                  });*/
                    Ivan K.
                    02 мая 2025, 12:42
                    0
                    Вот пример как вызываю
                    <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}
                      Виктор
                      03 мая 2025, 20:29
                      0
                      Пока не зводится( Скрипт заменил, но все так же подменяет по одной фотке, а гелерею целиком не тянет. Спасибо, что уделили время! Будем дальше думать
                        Ivan K.
                        03 мая 2025, 20:44
                        0
                        А целую галерею) я не так понял, думал одну фотку менять, у меня из коробки и одна не менялась (фотораму не использую на сайте) два часа возился. Как целую галерею менять подсказать не могу не использовал ни когда.
                          Виктор
                          04 мая 2025, 12:09
                          0
                          По одной фотке тоже не менялось. Баг какой-то, похоже. В ТП Володя помог. А вот по этой заметке хотелось бы менять группу фото, но это уже не работает(
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              33