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

Александр
Александр
1,7K
20
Содержание:
  1. Комментарии
Александр здравствуйте! Подскажите пожалуйста и если возможно то примером, при нажатии на ссылку (Второго или третьего варианта) в данном случае речь идёт о альтернативном виде 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>

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

  1. Александр Мальцев
    Александр Мальцев
    2019-10-31 14:00:06
    Привет!
    Для удобной работы на стороне клиента можно использовать библиотеку 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. Александр
    Александр
    2019-11-04 00:33:34
    Александр огромное спасибо, практически то что нужно, но есть одна проблема, класс меняется после перезагрузки страницы а как в данном случае, сделать чтобы налету менялся?
  • Александр Мальцев
    Александр Мальцев
    2019-11-06 14:01:17
    Для этого нужно к элементу добавить какой-то опозновательный признак, например 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);
    });
    
  • Александр
    Александр
    2019-11-08 15:39:13
    Александр здравствуйте! Спасибо, этот вариант работает как нужно, только не понятно почему при перезагрузке страницы класс сбрасывается, подскажите пожалуйста, как сделать чтобы не сбрасывался?

    И если возможно, к примеру, посетитель когда то выбрал альтернативный вид, как сделать чтобы при переходе на страницу каталога по прямой ссылке его выбор всё равно учитывался а сейчас получается так, выбираю вид он изменился, перехожу на главную, далее опять в каталог, вид становиться по умолчанию, выбор не учитывается, так как в ссылке отсутствует &tpl=2, как можно сделать, чтобы запоминался выбор на определённое время и пока посетитель сам не изменит вид?
  • Александр Мальцев
    Александр Мальцев
    2019-11-10 11:15:41
    Привет!
    Нужно указать количество дней сколько хранить куку:
    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');
        }
      }
    });
    
  • Александр
    Александр
    2019-11-10 13:33:36
    Александр спасибо, сейчас при перезагрузке страницы всё сохраняется, но есть две проблемы, как сделать чтобы при переключении браузерных вперёд назад, тоже всё работало, сейчас получается так: выбираю вид, класс изменился как нужно, нажимаю в браузере на стрелку вернуться на предыдущую страницу, вид становиться по умолчанию всё правильно а класс остаётся не изменённым, как сделать чтобы учитывались браузерные вперёд назад?

    Так же не получается сделать чтобы учитывался выбор вида при заходе по прямой ссылке, есть ссылка на каталог, пример: сайт/каталог, перейдя по такой ссылке, вид будет по умолчанию не зависимо от того был ли он выбран или нет а как сделать чтобы учитывался выбор пользователя и в зависимости от этого добавлялось к ней (&tpl=) к примеру пару дней назад я выбрал вид на сайте, захожу сегодня на сайт на главную в меню перехожу по ссылке: сайт/каталог и попадаю в каталог с тем видом что я выбирал, то есть к ссылке добавилось сайт/каталог&tpl=2 как это сделать?
  • Александр Мальцев
    Александр Мальцев
    2019-11-14 14:06:38
    Привет! Если браузерные back и forward приводят к переходам, то ничего добавлять не нужно, код JavaScript должен выполняться и изменять класс.
    Вторую часть, если правильно понял, вам нужно выполнить средствами MODX. Создать плагин на OnHandleRequest и написать в нём код для перенаправления пользователя на нужную страницу.
  • Александр
    Александр
    2019-11-14 23:38:15
    Александр, с mfilter2 почему то, это не работает. К примеру нажимаю на альтернативный вид «Плитка» к ссылке добавляется &tpl=1 класс блока test1, далее нажимаю на вид «Список» к ссылке добавляется &tpl=2 класс блока становиться test2, теперь нажимаю на браузерную back, в ссылке изменяется на &tpl=1 а класс почему-то не меняется и остаётся test2, может это связано с тем что в mFilter2 при нажатии на браузерную back, страница не перезагружается а аяксом всё делается может поэтому класс не изменяется?
  • Александр Мальцев
    Александр Мальцев
    2019-11-15 12:31:11
    В mFilter2 для этого есть же событие mse2_load. В обработчик этого события просто добавьте нужный код:
    $(document).on('mse2_load', function(){
      ...
    });
    
  • Александр
    Александр
    2019-11-15 23:19:54
    Пробую таким образом:
    $(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);
    		});
    но проблема остаётся, не правильно возможно что-то делаю?
  • Александр Мальцев
    Александр Мальцев
    2019-11-17 03:43:06
    Событие назваыется mse2_load, а не click. Поэтому нужно так:
    $(document).on('mse2_load', function(){
      var
        dataTpl = $(this).attr('data-tpl'),
        test = $('#test');
        // и т.д. код... 
    });
    
    А прописывать условия, если они нужны нужно уже в обработчике.
  • Александр
    Александр
    2019-11-18 02:26:49
    Александр спасибо за ответ я изначально так и делал но у меня не работало потом уже полез в скрипт 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?
  • Александр Мальцев
    Александр Мальцев
    2019-11-20 14:21:20
    А что при браузерных 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);
    
  • Александр
    Александр
    2019-11-20 17:13:54
    Событие 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, просто мигает но не изменяется, даже на то время пока происходит событие.
  • Александр Мальцев
    Александр Мальцев
    2019-11-21 14:21:14
    Значит событие 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)
    ;
  • Александр
    Александр
    2019-11-21 20:36:48
    Спасибо, сейчас ситуация такая, нажимая на изменить вид, всё работает как и работало с изначальным вариантом кода, класс изменяется с cookies тоже проблем нет, но back и forward по прежнему не работает, на событие тоже не реагирует с чем это может быть связано?

    Этот параметр:
    $(document).ready(myfunc);
    я убрал, так как если с ним то проблемы с куками при перезагрузки страницы.
  • Александр Мальцев
    Александр Мальцев
    2019-11-22 13:21:44
    Для работы с историей в браузере есть событие popstate. Попробуйте поработать с этим событием:
    window.addEventListener('popstate', function (e) {
    
    });
  • Александр
    Александр
    2019-11-22 17:57:25
    Сделал так, вернул в 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 не чего не происходит, возможно я что-то не правильно делаю?
  • Александр
    Александр
    2019-11-22 18:27:33
    Александр как я понимаю, событие сейчас срабатывает, так как класс сбросился при нажатии на back, но как правильно сделать, чтобы работало как нужно?
  • Александр Мальцев
    Александр Мальцев
    2019-11-24 11:37:19
    Не знаю, нужно разбираться из-за чего это. Какой код это выполняет, может это на клиенте, а может и на сервере…