Изменить css класс блока и сохранить выбор в куки

Александр
959
0
Александр здравствуйте! Подскажите пожалуйста и если возможно то примером, при нажатии на ссылку (Второго или третьего варианта) в данном случае речь идёт о альтернативном виде mFilter2, как можно изменить класс блока (тест) и сохранять выбор в cookies, пока не будет выбран (Первый вариант)?

Блок вывода ссылок для выбора альтернативного вида в mFilter2:
[[!+my.tpls:notempty=`
<div id="mse2_tpl" class="vid" >
	<a href="#" data-tpl="0" class="[[+my.tpl0]]"> (Первый вариант)</a>
	<a href="#" data-tpl="1" class="[[+my.tpl1]]"> (Второй вариант)</a>
	<a href="#" data-tpl="2" class="[[+my.tpl2]]"> (Третий вариант)</a>
</div>
`]]
Блок (тест):
<div class="test">Тест</div>

Комментарии ()

  1. Александр Мальцев
    31 октября 2019, 14:00
    Привет!
    Для удобной работы на стороне клиента можно использовать библиотеку js-cookie. Как с ней работать описано здесь.
    Сохранить выбор в cookie можно осуществить так:
    <script src="js.cookie-2.2.1.min.js"></script>
    <script>
      $(document).on('click', '.vid a', function(){
        Cookies.set('vid', $(this).attr('data-tpl'));
      })
    </script>
    
    На сервере можно создать сниппет, например, getVid:
    <?php
    if($_COOKIE['vid'] == '1') {
      return 'test1';
    } else if ($_COOKIE['vid'] == '2') {
      return 'test2';
    } else {
      return 'test';
    }
    
    Далее в шаблоне:
    <div class="[[!getVid]]">Тест</div>
    
    1. Александр
      04 ноября 2019, 00:33
      Александр огромное спасибо, практически то что нужно, но есть одна проблема, класс меняется после перезагрузки страницы а как в данном случае, сделать чтобы налету менялся?
      1. Александр Мальцев
        06 ноября 2019, 14:01
        Для этого нужно к элементу добавить какой-то опозновательный признак, например id:
        <div id="test" class="test">Тест</div>
        
        JS код:
        $(document).on('click', '.vid a', function () {
          var
            dataTpl = $(this).attr('data-tpl'),
            test = $('#test');
          test.removeClass();
          if (dataTpl === '1') {
            test.addClass('test1');
          } else if (dataTpl === '2') {
            test.addClass('test2');
          } else {
            test.addClass('test');
          }
          Cookies.set('vid', dataTpl);
        });
        
        1. Александр
          08 ноября 2019, 15:39
          Александр здравствуйте! Спасибо, этот вариант работает как нужно, только не понятно почему при перезагрузке страницы класс сбрасывается, подскажите пожалуйста, как сделать чтобы не сбрасывался?

          И если возможно, к примеру, посетитель когда то выбрал альтернативный вид, как сделать чтобы при переходе на страницу каталога по прямой ссылке его выбор всё равно учитывался а сейчас получается так, выбираю вид он изменился, перехожу на главную, далее опять в каталог, вид становиться по умолчанию, выбор не учитывается, так как в ссылке отсутствует &tpl=2, как можно сделать, чтобы запоминался выбор на определённое время и пока посетитель сам не изменит вид?
          1. Александр Мальцев
            10 ноября 2019, 11:15
            Привет!
            Нужно указать количество дней сколько хранить куку:
            Cookies.set('vid', dataTpl, { expires: 365 });
            При загрузке страницы должно с помощью сниппета меняться.
            Если нужно через JavaScript то можно так:
            $(function(){
              var
                vid = Cookies.get('vid'),
                test = $('#test');
              if (vid !== 'undefined') {  
                test.removeClass();
                if (vid == '1') {
                  test.addClass('test1');
                } else if (vid == '2') {
                  test.addClass('test2');
                } else {
                  test.addClass('test');
                }
              }
            });
            
            1. Александр
              10 ноября 2019, 13:33
              Александр спасибо, сейчас при перезагрузке страницы всё сохраняется, но есть две проблемы, как сделать чтобы при переключении браузерных вперёд назад, тоже всё работало, сейчас получается так: выбираю вид, класс изменился как нужно, нажимаю в браузере на стрелку вернуться на предыдущую страницу, вид становиться по умолчанию всё правильно а класс остаётся не изменённым, как сделать чтобы учитывались браузерные вперёд назад?

              Так же не получается сделать чтобы учитывался выбор вида при заходе по прямой ссылке, есть ссылка на каталог, пример: сайт/каталог, перейдя по такой ссылке, вид будет по умолчанию не зависимо от того был ли он выбран или нет а как сделать чтобы учитывался выбор пользователя и в зависимости от этого добавлялось к ней (&tpl=) к примеру пару дней назад я выбрал вид на сайте, захожу сегодня на сайт на главную в меню перехожу по ссылке: сайт/каталог и попадаю в каталог с тем видом что я выбирал, то есть к ссылке добавилось сайт/каталог&tpl=2 как это сделать?
              1. Александр Мальцев
                14 ноября 2019, 14:06
                Привет! Если браузерные back и forward приводят к переходам, то ничего добавлять не нужно, код JavaScript должен выполняться и изменять класс.
                Вторую часть, если правильно понял, вам нужно выполнить средствами MODX. Создать плагин на OnHandleRequest и написать в нём код для перенаправления пользователя на нужную страницу.
                1. Александр
                  14 ноября 2019, 23:38
                  Александр, с mfilter2 почему то, это не работает. К примеру нажимаю на альтернативный вид «Плитка» к ссылке добавляется &tpl=1 класс блока test1, далее нажимаю на вид «Список» к ссылке добавляется &tpl=2 класс блока становиться test2, теперь нажимаю на браузерную back, в ссылке изменяется на &tpl=1 а класс почему-то не меняется и остаётся test2, может это связано с тем что в mFilter2 при нажатии на браузерную back, страница не перезагружается а аяксом всё делается может поэтому класс не изменяется?
                  1. Александр Мальцев
                    15 ноября 2019, 12:31
                    В mFilter2 для этого есть же событие mse2_load. В обработчик этого события просто добавьте нужный код:
                    $(document).on('mse2_load', function(){
                      ...
                    });
                    
                    1. Александр
                      15 ноября 2019, 23:19
                      Пробую таким образом:
                      $(document).on('click', '.vid a', 'mse2_load',   function(e, data) {
                       var
                       dataTpl = $(this).attr('data-tpl'),
                        test = $('#test');
                        test.removeClass();
                        if (dataTpl === '1') {
                          test.addClass('test1');
                        } else if (dataTpl === '2') {
                          test.addClass('test2');
                        } else {
                          test.addClass('test');
                        }
                        Cookies.set('vid', dataTpl);
                      
                      objSSF.addSelectedFilters(ss_form_filter_css_id+" "+ss_container_filter_el,ss_container_filter_el, ss_type_filtered);
                      		});
                      но проблема остаётся, не правильно возможно что-то делаю?
                      1. Александр Мальцев
                        17 ноября 2019, 03:43
                        Событие назваыется mse2_load, а не click. Поэтому нужно так:
                        $(document).on('mse2_load', function(){
                          var
                            dataTpl = $(this).attr('data-tpl'),
                            test = $('#test');
                            // и т.д. код... 
                        });
                        
                        А прописывать условия, если они нужны нужно уже в обработчике.
                        1. Александр
                          18 ноября 2019, 02:26
                          Александр спасибо за ответ я изначально так и делал но у меня не работало потом уже полез в скрипт mfilter2 и там в функции mse2_load, пытался добавить код, не совсем ясно честно говоря, сейчас в шаблоне у меня так:
                          <script>
                          $(document).on('mse2_load', function(){
                            var
                               dataTpl = $(this).attr('data-tpl'),
                              test = $('#test');
                            test.removeClass();
                            if (dataTpl === '1') {
                              test.addClass('test1');
                            } else if (dataTpl === '2') {
                              test.addClass('test2');
                            } else {
                              test.addClass('test');
                            }
                            Cookies.set('vid', dataTpl);
                          });
                          </script>
                          <script>
                          $(document).on('click', '.vid a', function () {
                            var
                              dataTpl = $(this).attr('data-tpl'),
                              test = $('#test');
                            test.removeClass();
                            if (dataTpl === '1') {
                              test.addClass('test1');
                            } else if (dataTpl === '2') {
                              test.addClass('test2');
                            } else {
                              test.addClass('test');
                            }
                            Cookies.set('vid', dataTpl);
                          });
                          </script>
                          Я понимаю что делаю не правильно, но не могу допереть что и куда и по поводу обработчика, тоже не понял, подскажите пожалуйста как в данном случае правильно прописать, чтобы работали браузерные back и forward?
                          1. Александр Мальцев
                            20 ноября 2019, 14:21
                            А что при браузерных back и forward событие mse2_load не происходит?
                            Воспользуйтесь отладчиком кода в браузере или хотя бы просто добавьте в функцию вывод какого-нибудь значения в консоль.
                            $(document).on('mse2_load', function(){
                              console.log('mse2_load');
                              ...
                            });
                            Если сообщение в консоли выводится, то событие значит происходит.
                            А почему думаете, что делаете что-то неправильно? Если один и тот же код должен выполняться при разных событиях, то по-другому не так.
                            Но такой код, конечно, нужно упростить. Для этого нужно создать функцию, а затем указать её в качестве обработчиков нужных событий.
                            var myfunc = function() { ... }
                            $(document).on('mse2_load', myfunc);
                            $(document).on('click', '.vid a', myfunc);
                            Кроме этого, возможно вам код нужно выполнять не только при наступлении этих событий, а также, например после загрузки страницы:
                            $(document).ready(myfunc);
                            
                            1. Александр
                              20 ноября 2019, 17:13
                              Событие mse2_load происходит, но если посмотреть в консоле, код, класс test видно мигает, но не изменяется, это если при нажатии back и forward.

                              Что самое интересное при изменении вида, перестаёт правильно работать изменение класса блока, это если используешь событие mse2_load, происходит следующее, нажимаю изменить вид, класс блока test на доли секунды изменяется как и необходимо, именно на то время, пока происходит событие mse2_load и становиться по дефолту.

                              Так же если посмотреть в консоле куки что-то не то твориться при нажатии на вид на доли секунды появляется нужная запись и сразу меняется на (undefined).

                              Делаю так:
                              <script>
                              var myfunc = function() {  dataTpl = $(this).attr('data-tpl'),
                                  test = $('#test');
                                test.removeClass();
                                if (dataTpl === '1') {
                                  test.addClass('test1');
                                } else if (dataTpl === '2') {
                                  test.addClass('test2');
                                } else {
                                  test.addClass('test'); 
                                }
                                 console.log('mse2_load');
                                Cookies.set('vid', dataTpl); 
                              }
                              $(document).on('mse2_load', myfunc);
                              $(document).on('click', '.vid a', myfunc);
                              $(document).ready(myfunc);
                              </script>
                              <script>
                              $(function(){
                                var
                                  vid = Cookies.get('vid'),
                                  test = $('#test');
                                if (vid !== 'undefined') {  
                                  test.removeClass();
                                  if (vid == '1') {
                                    test.addClass('test1');
                                  } else if (vid == '2') {
                                    test.addClass('test2');
                                  } else {
                                    test.addClass('test');
                                  }
                                }
                              });
                              </script>
                              Александр, да по этому я и подумал что не правильно делаю, так как размещаю один и тот же код несколько раз, спасибо сейчас более понятно по этому поводу.

                              Если всё обобщить, сейчас выглядит примерно так, пока происходит событие mse2_load, всё срабатывает ненадолго, кроме back и forward так как при нажатии на них, класс test, просто мигает но не изменяется, даже на то время пока происходит событие.
                              1. Александр Мальцев
                                21 ноября 2019, 14:21
                                Значит событие mse2_load не подходит. В этом случае нужно внести изменения в файл "\assets\components\msearch2\js\web\default.js":
                                afterLoad: function () {
                                  $(this.options['wrapper']).removeClass( this.options['loading_class']);
                                  this.results.css('opacity', 1);
                                  this.filters.find('.' + this.options.disabled_class).prop('readonly', false).removeClass(this.options.disabled_class);
                                  $(document).trigger('mse2_afterload');
                                },
                                
                                После этого изменить:
                                $(document).on('mse2_afterload', myfunc)
                                ;
                                1. Александр
                                  21 ноября 2019, 20:36
                                  Спасибо, сейчас ситуация такая, нажимая на изменить вид, всё работает как и работало с изначальным вариантом кода, класс изменяется с cookies тоже проблем нет, но back и forward по прежнему не работает, на событие тоже не реагирует с чем это может быть связано?

                                  Этот параметр:
                                  $(document).ready(myfunc);
                                  я убрал, так как если с ним то проблемы с куками при перезагрузки страницы.
                                  1. Александр Мальцев
                                    22 ноября 2019, 13:21
                                    Для работы с историей в браузере есть событие popstate. Попробуйте поработать с этим событием:
                                    window.addEventListener('popstate', function (e) {
                                    
                                    });
                                    1. Александр
                                      22 ноября 2019, 18:27
                                      Александр как я понимаю, событие сейчас срабатывает, так как класс сбросился при нажатии на back, но как правильно сделать, чтобы работало как нужно?
                                      1. Александр Мальцев
                                        24 ноября 2019, 11:37
                                        Не знаю, нужно разбираться из-за чего это. Какой код это выполняет, может это на клиенте, а может и на сервере…
                                      2. Александр
                                        22 ноября 2019, 17:57
                                        Сделал так, вернул в default.js всё как было, скрипт поставил тот, что изначально был и добавил второй:

                                        <script>
                                        window.addEventListener('popstate', function (e) {
                                          dataTpl = $(this).attr('data-tpl'),
                                            test = $('#test');
                                          test.removeClass();
                                          if (dataTpl === '1') {
                                            test.addClass('test1');
                                          } else if (dataTpl === '2') {
                                            test.addClass('test2');
                                          } else {
                                            test.addClass('test');
                                          }
                                         Cookies.set('vid', dataTpl);
                                        });
                                        </script>
                                        Сейчас происходит так, всё что работало так и работает но при нажатии на браузерную back, класс сбрасывается на test и в куках undefined при дальнейших нажатиях на back или forward не чего не происходит, возможно я что-то не правильно делаю?
      Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.