Динамическое отображение цены в карточке товара



  • Здравствуйте. Сделал дополнительные параметры для товара. В корзину все добавляется и цена там считается нормально, но вот в карточке товара цена не обновляется, при клике по чекбоксу. В консоли пишет - SHK is not defined.

    Код карточки товара

    <div class="card_image">
      <img src="[[*product_image]]" alt="">
    </div>
    <div class="card_info">
      <form action="[[~[[*id]]? &scheme=`abs`]]" method="post" class="card_form" style="display: block;">
          	<table class="card_params shk-item" border="0">
               <tr>
                   <td>Номер в каталоге</td>
                   <td>[[*product_id]]</td>
               </tr>
               <tr>
                   <td>Материал</td>
                   <td>[[*product_material]]</td>
               </tr>
               <tr>
                   <td>Стоимость</td>
                   <td><span class="card_price shk-price">[[*product_price]]</span></td>
               </tr>       
           	</table>
    
          </div>
          <div class="card_option">
              <span>Дополнительные опции</span><br />
              <div class="opt">
                  [[*params:replace=`[[+id]]==[[*id]]`]]
              </div>
          </div>
            
            <input type="hidden" name="shk-id" value="[[*id]]" />
            <input type="hidden" name="shk-name" value="[[*pagetitle]]" />
            <input type="hidden" name="shk-count" value="1" />
                                    
            <div class="card_button">
                <button type="submit" class="shk-but details" style="padding: 7px 15px !important"><i class="fa fa-shopping-cart" aria-hidden="true"></i></button>
              <a class="fancybox" href="#callback">
                  <button>Заказать в 1 клик</button>
              </a>
            </div>
      </form>
    
    </div>
    

    доп. параметр - params
    параметры ввода - param-edit
    параметры вывода:

    • shk_chekbox
    • SHK.additOpt(this)
    • shk_param
    • div
    • нет
    • params

    в опциях ввода параметров все указываю верно - перед параметром цены ставлю + или * (в зависимости от требований)

    В чем проблема? Я понимаю что где-то в карточке товара что-то не так указал, но разглядеть не могу.(( Да и в корзине же считается все...

    Помогите!

    noJquery везде отключен.



  • Так из коробки и нет динамического обновления цены, нужно писать обработчик на js.
    Для себя я написал маленький скрипт, который обрабатывает вывод любого кол-ва доп. параметров с ценой, для всех трех типов radio, checkbox, select-one.
    Настройка:

    1. В настройках tv-параметра (в Параметрах вывода) заменил название обработчика событий SHK.additOpt(this) на свой selectParam(this)

    2. Значение цены должно быть в теге с id="cena", для цены по акции с id="cena_action"

    <div class="price">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]</span></div>```
    
    1. В конец чанка, после вывода формы добавить скрипт.
      Получится как то так (глубоко объяснять свой чанк товара не буду, чтобы не засорять пространство.):
    <form action="[[*uri]]" method="post">
    		  <input type="hidden" name="shk-name" value="[[*pagetitle]]" />
    		  <input type="hidden" name="shk-count" value="1" />
    		  
    		  [[*complectation:!empty=`<div class="dop-param-name">Дополнительная комплектация:</div><div class="param_select">[[*complectation:replace=`[[+id]]==[[*id]]`]]</div>`]]
    		  [[*servis:!empty=`<div class="dop-param-name">Сервис:</div><div class="param_select">[[*servis:replace=`[[+id]]==[[*id]]`]]</div>`]]
    		  [[*obsluj:!empty=`<div class="dop-param-name">Гарантия:</div><div class="param_select">[[*obsluj:replace=`[[+id]]==[[*id]]`]]</div>`]]
    
    			[[*action:is=`*1*`:then=`<input type="hidden" name="act__[[*id]]__add"  value="акция" />
    			<input type="hidden" name="shk-id" value="[[*id]]__price_action" />
    			<div class="price action-no">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]</span></div>
    			<div class="price-action">Цена по акции: <span id="cena_action">[[*price_action:num_format]]</span> <span id="currency_action">[[++shk3.currency]]</span></div>
    			`:else=`<input type="hidden" value="[[*id]]" name="shk-id" />
    			<div class="price">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]</span></div>
    			`]]
    		  <button type="submit" name="shk-submit"></button>
    		</form>
    <script>
      var addPrice=0; //Сумарная наценка за опции
      var options = {}; //Объект для хранения выбранных опций и их цены
      var PriceCarent = document.getElementById("cena").innerHTML; //получаю значение Цены в тегах с id cena;
      PriceCarent=Number(PriceCarent.replace(/\s+/g,''));//вырезаю пробелы и табуляции, и превращаю в число;
      
      //Тоже самое делаю для цены по акции
      var PriceCarentAction = document.getElementById("cena_action").innerHTML;
      PriceCarentAction=Number(PriceCarentAction.replace(/\s+/g,''));
      
      function selectParam(element) {
    	//console.log(element);	
    	var TypeParam = element.type; //получаю значение атрибута type -> Тип списка (radio, checkbox, select-one)
    	//console.log("TypeParam=" + TypeParam);
    
    	//получаю значение атрибута value
    	if (TypeParam == "select-one") //для select-one (выпадающий список с одиночным выбором)
    	{
    	  var idSelect = element.id; //получаю значение атрибута id
    	  //console.log("id=" + idSelect);
    	  var sel = document.getElementById(idSelect); // Получаем наш список
    	  var valueSelect = sel.options[sel.selectedIndex].value; // Получаем значение выделенного (selected="selected") элемента
    	  //console.log("valueSelect=" + valueSelect);
    	  var param = valueSelect;
    	}
    	else var param = element.value; //для переключателей radio и checkbox
    
    	//Цена опции
    	var pos = param.indexOf("__") + 2;
    	var PriceParam = Number(param.substring(pos));
    	//console.log("PriceParam=" + PriceParam);
    
    	//Имя опции	
    	var NameParam = element.name; //получаю значение атрибута name
    	//console.log("NameParam=" + NameParam);
    
    
    //Формирую объект (массив) с названиями выбранных опций и их цен
    	if(TypeParam == "radio" || TypeParam == "select-one") { //console.log("Click for RADIO or SELECT");
    	  options [NameParam] = PriceParam;
    	}
    	else { //console.log("Click for CHECKBOX");
    	  if (options [NameParam] > 0) 	options [NameParam] = 0;
    	  else options [NameParam] = PriceParam;
    	  //console.log(options);
    	} 
    	
    	var addPrice=0;
    	for (var key in options) { // Перебор всех свойств объекта console.log( "Ключ: " + key + " значение: " + options[key] );
    	  addPrice += options[key]; //Суммирую все цены доп. опций
    	}
    
    	// Вывожу в заданный блок с Id - Подменяю значения цен в блоке с ценой для покупателя
    	if (PriceCarent > 0) {
    	  var PriceSum = String(PriceCarent + addPrice); //Преобразовываю сумму цен в строку
    	  PriceSum = PriceSum.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 '); //разделяю разряды цифры пробелом
    	  document.getElementById("cena").innerHTML = PriceSum;
    	}
    	if (PriceCarentAction > 0) {
    	  var PriceSumAction = String(PriceCarentAction + addPrice);
    	  PriceSumAction = PriceSumAction.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
    	  document.getElementById("cena_action").innerHTML = PriceSumAction;
    	}
      }
    </script>
    

    P.S. Много камней не кидайте, js вообще не знаю. Но скрипт рабочий :)

    Если цена по акции не нужна, то все еще проще:

    <form action="[[*uri]]" method="post">
    		  <input type="hidden" name="shk-name" value="[[*pagetitle]]" />
    		  <input type="hidden" name="shk-count" value="1" />
                      <input type="hidden" value="[[*id]]" name="shk-id" />
    		  
    		  [[*complectation:!empty=`<div class="dop-param-name">Дополнительная комплектация:</div><div class="param_select">[[*complectation:replace=`[[+id]]==[[*id]]`]]</div>`]]
    		  [[*servis:!empty=`<div class="dop-param-name">Сервис:</div><div class="param_select">[[*servis:replace=`[[+id]]==[[*id]]`]]</div>`]]
    		  [[*obsluj:!empty=`<div class="dop-param-name">Гарантия:</div><div class="param_select">[[*obsluj:replace=`[[+id]]==[[*id]]`]]</div>`]]
    		  <div class="price">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]
    		  <button type="submit" name="shk-submit"></button>
    </form>
    <script>
      var addPrice=0; //Сумарная наценка за опции
      var options = {}; //Объект для хранения выбранных опций и их цены
      var PriceCarent = document.getElementById("cena").innerHTML; //получаю значение Цены в тегах с id cena;
      PriceCarent=Number(PriceCarent.replace(/\s+/g,''));//вырезаю пробелы и табуляции, и превращаю в число;
      
      function selectParam(element) {
    	//console.log(element);	
    	var TypeParam = element.type; //получаю значение атрибута type -> Тип списка (radio, checkbox, select-one)
    	//console.log("TypeParam=" + TypeParam);
    
    	//получаю значение атрибута value
    	if (TypeParam == "select-one") //для select-one (выпадающий список с одиночным выбором)
    	{
    	  var idSelect = element.id; //получаю значение атрибута id
    	  //console.log("id=" + idSelect);
    	  var sel = document.getElementById(idSelect); // Получаем наш список
    	  var valueSelect = sel.options[sel.selectedIndex].value; // Получаем значение выделенного (selected="selected") элемента
    	  //console.log("valueSelect=" + valueSelect);
    	  var param = valueSelect;
    	}
    	else var param = element.value; //для переключателей radio и checkbox
    
    	//Цена опции
    	var pos = param.indexOf("__") + 2;
    	var PriceParam = Number(param.substring(pos));
    	//console.log("PriceParam=" + PriceParam);
    
    	//Имя опции	
    	var NameParam = element.name; //получаю значение атрибута name
    	//console.log("NameParam=" + NameParam);
    
    //Формирую объект (массив) с названиями выбранных опций и их цен
    	if(TypeParam == "radio" || TypeParam == "select-one") { //console.log("Click for RADIO or SELECT");
    	  options [NameParam] = PriceParam;
    	}
    	else { //console.log("Click for CHECKBOX");
    	  if (options [NameParam] > 0) 	options [NameParam] = 0;
    	  else options [NameParam] = PriceParam;
    	  //console.log(options);
    	} 
    	
    	var addPrice=0;
    	for (var key in options) { // Перебор всех свойств объекта console.log( "Ключ: " + key + " значение: " + options[key] );
    	  addPrice += options[key]; //Суммирую все цены доп. опций
    	}
    
    	// Вывожу в заданный блок с Id - Подменяю значения цен в блоке с ценой для покупателя
    	if (PriceCarent > 0) {
    	  var PriceSum = String(PriceCarent + addPrice); //Преобразовываю сумму цен в строку
    	  PriceSum = PriceSum.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 '); //разделяю разряды цифры пробелом
    	  document.getElementById("cena").innerHTML = PriceSum;
    	}
      }
    </script>
    


  • Это не критично, но увидел ошибку в варианте без цены по акции, не верно скопировал:
    строка

    <div class="price">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]
    

    нужно закрыть span и div:

    <div class="price">Цена: <span id="cena">[[*price:num_format]]</span> <span id="currency">[[++shk3.currency]]</span></div>
    


  • @Asderkdw а что за SHK.additOpt(this)?
    я так понял что этот метод добавляет опции товара к цене динамически. И вот при его вызове ошибка. Думаю что в этом проблема, так как на видео, которое я смотрел все работало без "велосипедов" на JS.

    Благодарю за помощь. Только вы откликнулись!



  • @finc_85 Возможно и было динамически раньше. Но у меня не заработал обработчик SHK.additOpt(this) и ответа на вопрос тоже не нашел. Потому и написал свой скриптик с обработкой.
    Собственно это просто путь для решения других не стандартных задач, потому и предпочел свой обработчик, который я понимаю как работает.
    И пожалуйста :)



  • @Asderkdw Ваш скрипт видимо умеет только складывать. А если требуются другие операции вычитание/умножение/деление?
    Для моей задачи нужны проценты, но я решил обойтись умножением *0.ХХ, а скрипт написал NaN.



  • Простите, а то что на демо-сайте
    http://demo.modx-shopkeeper.ru/katalog/planshetyi-i-telefonyi/msi-reiciendis-7893.html

    чем вас не устроило?



  • @slaad не работает SHK.additOpt(this) в стоке, пришлось искать велосипед в виде этого скрипта.



  • @Ren посмотрите как на демо сайте это реализовано, там ведь все работает.

    http://forum.modx-shopkeeper.ru/topic/50/демо-сайт-shopkeeper-3-x



  • @slaad с демкой так и не разобрался. В демке: тв-шка - params, в шаблоне вызывается [[*param1]]. У каждого товара есть два параметра 500 и 1000. Ставим галки, все плюсуется.
    Делаю тоже самое у себя. Но при вызове [[*param1]] конечно пусто, ведь она называется paramS. А если вызвать одноименную то список выводится, а ничего не работает.
    В итоге вопрос - почему в демке указано именно param1, и как это влияет, откуда берется?

    p.s. в демке кстати у инпутов name="param1__138__0" и т.д., а у меня name="params__" на всех.



  • Эта запись удалена!


  • @Ren я понимаю, что проще вопросы задать, но для кого же доки пишут?))

    почитайте раздел Дополнительные параметры товаров:
    http://wiki.modx-shopkeeper.ru/doku.php?id=shopkeeper3
    вот чувствую, что пришли не читая и задали вопрос, что ничего не работает, оно и не будет.



  • @slaad плохое у вас чутье. я с шопкипером еще с первой версии. доки эти уже наизусть знаю. но тут прям засада.
    уже сделал, что параметры нормально отображаются:

    <div><input class="shk_param" type="radio" name="params__101" value="0__1" id="params1010" onclick="SHK.additOpt(this)" /> <label for="params1010">Плюс 1</label></div>
    <div><input class="shk_param" type="radio" name="params__101" value="1__1000" id="params1011" onclick="SHK.additOpt(this)" /> <label for="params1011">Плюс 1000</label></div>
    <div><input class="shk_param" type="radio" name="params__101" value="2__*2" id="params1012" onclick="SHK.additOpt(this)" /> <label for="params1012">Умножить на 2</label></div>
    

    И нифига...



  • @slaad Разобрался. Оказывается все работает, в корзину прилетает правильная цена и появляется поле с "дополнительным параметром", но на странице товара обновление цены не происходит в связи с одной простой мелочью. Тег цены на сайте должен иметь класс "shk-price". В инструкции (ни в этой http://wiki.modx-shopkeeper.ru/doku.php?id=shk3_docs ни в этой http://wiki.modx-shopkeeper.ru/doku.php?id=shopkeeper3) вообще об этом ни слова.

    Теперь у меня и конвертирует по курсу и обновляет цену плюсуя и умножая.



Похоже, подключение к Форум | MODX Shopkeeper было разорвано, подождите, пока мы пытаемся восстановить соединение.