jQuery: запускает функцию только тогда, когда определенный медиа-запрос имеет значение true

#jquery #media-queries

#jquery #медиа-запросы

Вопрос:

У меня есть функция jQuery, которая должна запускаться только тогда, когда определенный медиа-запрос имеет значение true (как при готовности, так и при изменении размера).

Я нашел классный трюк, чтобы проверить, является ли определенный медиа-запрос истинным:

HTML

 <div id="isthin"></div>
  

CSS

 #isthin {
    display: inline-block;
    content: '';
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media only screen and (max-width: 1047px) {
    #isthin {
        display: none;
    }
}
  

jQuery

 $(document).ready(function(){
    if ( $('#isthin').is(":visible") ) {
        // function should be fired
    } else {
        // function should not be fired
    }
});

$(window).resize(function(){
    if ( $('#isthin').is(":visible") ) {
        // function should be fired
    } else {
        // function should not be fired
    }
});
  

Отдельная функция jQuery

 $(function () {
      $('nav li ul').hide().removeClass('sub-nav');
      $('nav li').hover(function () {
        $('ul', this).stop().slideToggle(300);
      });
});    
  

Это была моя логика, но каким-то образом функция все еще выполняется при изменении размера при изменении медиа-запроса.

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

1. Вы когда-нибудь слышали о matchmedia ?

2. Да, но я должен поддерживать IE9 …

3. Это прискорбно…

4. Ну, у вас отсутствует скобка, но как только вы ее добавите, она заработает: jsfiddle.net/uLq5L

5. О, я добавил парантезис. Ваша скрипка работает, но если я не переопределяю или не останавливаю функцию, она каким-то образом все равно выполняется …

Ответ №1:

Основываясь на ваших фрагментах, я открыл этот скрипт в браузере:

 <html>
  <head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <style type="text/css">
    #isthin {
      display: inline-block;
      content: '';
      width: 1px;
      height: 1px;
      overflow: hidden;
      border: 1px solid red;
   }
   @media only screen and (max-width: 1047px) {
      #isthin {
        display: none;
      }
  }
  </style>

  <script type="text/javascript">    
    $(document).ready(function(){
      if ( $('#isthin').is(":visible") ) {
        // function should be fired
        console.log("[doc ready] Media Query wide");
      } else {
        // function should not be fired
        console.log("[doc ready] Media Query thin");
      }
   });

   $(window).resize(function(){
     if ( $('#isthin').is(":visible") ) {
        // function should be fired
        console.log("[Resize] Media Query wide");
     } else {
        // function should not be fired
        console.log("[Resize] Media Query thin");
     }
   });
</script>
</head>
  <body>
    <div id="isthin"><id>
  </body>
</html>
  

Если я снова сужу и расширяю браузер, я вижу сообщения консоли такими, какими они должны быть:

 [doc ready] Media Query wide 
[Resize] Media Query wide 
[Resize] Media Query wide 
[Resize] Media Query wide 
[Resize] Media Query wide 
...
...
[Resize] Media Query thin 
[Resize] Media Query thin 
[Resize] Media Query thin 
[Resize] Media Query thin 
...
[Resize] Media Query wide
...
...
  

Поэтому я думаю, что ваш способ обнаружения медиа-запроса правильный (и сложный). Я предлагаю вам проверить:

  • если это проблема, связанная с браузером,
  • как ваша отдельная функция jQuery связана с обратным вызовом изменения размера.

Тогда учтите, что в этом случае вы не экономите часть работы, используя CSS-запросы. Вам все равно нужен обратный вызов resize. Итак, посмотрите на этот другой элегантный способ, который я видел для решения этой проблемы. Это наоборот, избегая селекторов CSS, но делая то же самое:

 $(window).resize(function(){
    if ( $(window).width() < xxxx amp;amp; $(window).width() > yyyyy ) {

        $('body').addClass('phone');  // <<<<<<<<<<<<<<
        $('body').removeClass('tablet');
        $('body').removeClass('workstation');

    } else if ( ... ) {

        $('body').removeClass('phone');
        $('body').addClass('tablet');  // <<<<<<<<<<<<<<
        $('body').removeClass('workstation');

    } 
    ...
    ...
}
  

Затем вы можете легко отличить в CSS, добавив .phone , .tablet и .workstation в селекторы и, возможно, удалить запросы. Далее:

 $(window).resize(function(){
    if ($('body').hasClass('phone')) {

       ...
       ...

    } else if ( ... ) {
       ...
    } 
    ...
    ...
}
  

Таким образом, у вас есть все это на стороне JS и меньше на стороне CSS.

Идея принадлежит не мне, я видел ее в рамках, но я не уверен, какой она была.

Ответ №2:

Проблема заключается не в самом медиа-запросе, а в том, как вы привязываете свое событие.

Вы привязываете его при каждом изменении размера, когда запрос подходит. Вы действительно должны отключить все свои функции и использовать флаг. Вот так :

 var flag = true;

$(window).resize(function(){

    flag =  $('#isthin').is(":visible");

    if(flag){
        $('nav li ul').hide().removeClass('sub-nav');
    }else{
        $('nav li ul').show().addClass('sub-nav');
    }

})

$(document).ready(function(){

    $(window).trigger('resize');
})

$(function () {
    $('nav li').hover(function () {
        if(flag){
            $('ul', this).stop().slideToggle(300);
        }
    });
});  
  

Скрипка

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

1. Большое вам спасибо за вашу помощь!