EzDevInfo.com

enquire.js

Awesome Media Queries in JavaScript Awesome Media Queries in JavaScript - enquire.js enquire.js is a lightweight, pure javascript library for responding to css media queries. it's totally awesome

How to Switch Between two Jquery Based Layouts (when using desktop and mobile)

I want to create a responsive website. If the browser is mobile sized, the content should be displayed with an iPhone Style List View If the browser is desktop sized, the content should be displayed with tabs:

enter image description here

What is the best way of doing this? I don't want to use separate files for Mobile/Desktop. I want it to be responsive.




Here is some of the research I have done.

Attempt 1: Pure CSS solution.

A pure CSS solution would be the best, as CSS offers media queries which makes it easy to switch between layouts. CSS offers methods for creating tabs. But it doesn't seem to offer a method for an iPhone style list. (You can almost fake it with an accordion list but this doesn't take the user to a separate page like on a true iPhone app).

Attempt 2: Jquery Solution (see Fiddle)

In this fiddle, I have tried to combine Jquery Mobile and Jquery Ui. Enquire.Js is used to call the necessary library depending on screen.

When a library is called, it will alter the dom structure. So the unneeded library has to be removed, otherwise if the user re-sizes the browser (i.e. switches between mobile desktop), the unused library will break cause conflicts for the called library.

In my fiddle, I have tried to do this, but it doesn't seem to work:

$(document).ready(function() {

        enquire.register("screen and (max-width: 600px)", function() {
    $('script[src~="jquery-ui.js"]').remove();
    $('link[rel=stylesheet][href~="jquery-ui.css"]').remove();    
     $('head').append('<link rel="stylesheet" rel='nofollow' href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />');    
     $('head').append('<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"><\/script>');   
        $("#tabs").tabs("destroy");            
    }).listen();


       enquire.register("screen and (min-width: 601px)", function() {
    $('script[src~="jquery.mobile-1.0a3.min.js"]').remove();
    $('link[rel=stylesheet][href~="jquery.mobile-1.0a3.min.css"]').remove();    
    $('head').append('<link rel="stylesheet" rel='nofollow' href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" />');        
     $('head').append('<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"><\/script>');    
    $("#tabs").tabs();

    }).listen();

});

Even though the unused library is removed, it causes conflicts for the new library. Also, you have to re-size the browser before any of the layouts are called. If the user doesn't re-size the browser, the content will be unstyled.

Attempt 3: Dom Cloning (see Fiddle)

This attempt is similar to attempt 2, except on page load it stores the DOM in a variable. Then when the user re-sizes the browser, the existing DOM is replaced with the stored DOM. I have followed the method outline here, but it doesn't seem to work. The dom is just removed instead of being replaced.

I would appreciate any helpful with this, as I have been tearing my hair out to find a solution! (I know I have asked a question similar to this, but I felt this new question was different enough to warrant a new post.)

Attempt 4: Dynamically Assigning Data Attributes

Jquery mobile uses data attributes in the mark up to make the scripts work. I have tried applying these dynamically, so they are only written to the document when the browser is at mobile size. However, when the browser is re-sized, the desktop tabs are still broken.


Source: (StackOverflow)

enquire.js legacy support

I'm trying to figure out what the best way to get enquire.js to work on legacy browsers (ie 6-9). On enquire's site, it says to use modernizr to check for matchMedia support, then load a polyfill if it's not supported.

Modernizr.load([
    //first test need for polyfill
    {
        test: window.matchMedia,
        nope: "/path/to/polyfill.js"
    },

    //and then load enquire
    "/path/to/enquire.js"
]);

Looking at the polyfill that it suggests, it says that modernizr already includes it with Modernizr.mq().

    Used in:
    Respond.js
    FormFactor
    Modernizr
https://github.com/paulirish/matchMedia.js/

I've looked into this, but can't find a way to make this work.


Source: (StackOverflow)

Advertisements

Enquire.js + Media.match + Respond.js

I'm trying to get Enquire.js working for legacy browsers. I'm using the Deep support method from the docs:

Modernizr.load([
    {
        test: window.matchMedia,
        nope: "media.match.min.js"
    },

    "enquire-2.0.0.min.js",
    "plugins.js", // jquery plugins
    "main.js" // enquire-triggered functions + general code
]);

The problem with this is I am using Modernizr+Respond from initializr.com, so the test always passes. This triggers a JS error in enquire.js in IE8/9.

By removing respond.js and just using plain Modernizr the test fails, Media.match loads, and the JS error is solved. However, I lose my Media Query support in IE8.

What's the best method to get everything working together? I have tried loading respond.js at the same time as Media.match via Modernizr. If I load it first, I see the same JS error as before. If I load it second, media queries don't work. I've also tried just loading that INSTEAD of Media.match, but the JS error returns.

Thanks.

EDIT:

Shortly after posting this I rolled back to enquire 1.5.6, used Respond.js, the shouldDegrade option, and no Modernizr tests. No JS errors in IE8/9, and everything seems to be working fine so far.

I am still interested to know if there's a way to get this working with 2.0, or if I should stick with the 1.5.6 for now?


Source: (StackOverflow)

enquire.js - How to maintain variables in dynamically created register functions?

I'm looping through an object containing multiple elements, with each containing multiple media queries.

In the loop, I'm dynamically calling enquire.js .register() to perform something on the match. This works initially, but outside of the loop, and upon resizing the browser, the matches no longer work, as the variables used in the loop have been incremented to their hightest value from the loop.

It's probably easier to explain in code!

Here's the images object:

var images = [
   {
      "selector":"[data-id=\"0\"]",
      "breakpoints":[
         {
            "mediaquery":"(max-width: 31.25em) ",
            "src":"image-0-small.jpg"
         },
         {
            "mediaquery":"(min-width: 31.3125em) and (max-width: 46.25em) ",
            "src":"image-0-medium.jpg"
         },
         {
            "mediaquery":"(min-width: 46.3125em) ",
            "src":"image-0-large.jpg"
         }
      ]
   },
   {
      "selector":"[data-id=\"1\"]",
      "breakpoints":[
         {
            "mediaquery":"(max-width: 31.25em) ",
            "src":"image-1-small.jpg"
         },
         {
            "mediaquery":"(min-width: 31.3125em) and (max-width: 46.25em) ",
            "src":"image-1-medium.jpg"
         },
         {
            "mediaquery":"(min-width: 46.3125em) ",
            "src":"image-1-large.jpg"
         }
      ]
   },
   {
      "selector":"[data-id=\"2\"]",
      "breakpoints":[
         {
            "mediaquery":"(max-width: 31.25em) ",
            "src":"image-2-small.jpg"
         },
         {
            "mediaquery":"(min-width: 31.3125em) and (max-width: 46.25em) ",
            "src":"image-2-medium.jpg"
         },
         {
            "mediaquery":"(min-width: 46.3125em) ",
            "src":"image-2-large.jpg"
         }
      ]
   }
];

And here's the loop:

for (var x=0; x < images.length; x++) {
  for (var y=0; y < images[x]['breakpoints'].length; y++) {
    enquire.register(images[x]['breakpoints'][y]['mediaquery'], function () {
      // x and y unfortuntaley equal 3 & 3 after the loop, so how do I maintain them from inside the match?
      // Interestingly, Firefox doesn't seem attempt to fire matches more than once. Chrome and IE 11 do, which is where I found the error that images[x] is undefined

      console.log('match-index', x, y);
      console.log('match-images', images);
      console.log('match-mediaquery', images[x]['breakpoints'][y]['mediaquery']);
    });
  }
}

images[x] is undefined because x = 3. How do I keep x and y to equal what was originally passed in on future matches?


Source: (StackOverflow)

Using Enquire.js and Media Queries Effectively for Jquery Animations

Hi i've been trying to get my head around how to use enquire.js. I am using .mouseenter(function() to activate the functions .show and .hide. But when you view it on a tablet and mobile .mouseenter becomes redundant. I want to tell the jquery to show the div once the screen width reaches my media query.

 @media only screen and (min-width : 769px ) and (max-width : 959px) 

Below is an example.

Here is my jquery:

$(".slidingDiv_how").hide(); 
          $(".show_sub").show(); 

          $('.show_sub').mouseenter(function(){
          $(".slidingDiv_how").slideDown();
            return false;
          });
            });

Here is my html

<div class"right-wrapper"><!--How wrapper -->
                                <div id="how_we" class="show_sub1" style="cursor: hand; cursor: pointer;">
                                    <h1><a rel='nofollow' href="#">How We Work:</a></h1>
                                        <div class="slidingDiv_how">
                                            <p class="show_sub1">The heat of the vertical rays of the sun was fast making our horrible prisons unbearable, so that after passing a low divide, and entering a sheltering forest, we finally.</br> 
                www.dochouse.co.uk</p>

                                        </div> <!-- end slidingdiv2 -->

I have read the documentation and don't really understand which part to put were. Any help would be much appreciated.


Source: (StackOverflow)

Destroy a Jquery function when media query changes

Hope you can help me out.

I have searched through the forums, I guess this one is a special case.

The project I am building are powered with media queries (Responsive), I have 3 columns, sometimes 4 to needs to be in equal height. I have developed a script in Jquery which works great. See below

var maxHeight = 0;
function setHeight(column) {
    $(window).load(function () {
        column = $(column);
        column.each(function () {
            if ($(this).height() > maxHeight) {
                maxHeight = $(this).height();
            }
        });

        column.height(maxHeight);
    });
}

setHeight('.package-container .package-3');

But when I am going to mobile version, below 767px, how do I destroy this setHeight() function without having to refresh the page.

Other alternative, I can do this below using enquire.js, javascript media query but I could not get it to work without having to refresh if I go straight from Desktop/tablet to mobile. Like this below

enquire.register("(max-width:767px)", {
    match : function() {
        setHeight(null);
    }
}).listen();

Source: (StackOverflow)

jQuery If/Else statement, to check if element has class produces both results?

I am using the enquire.js library to add JavaScript media queries into a site I am developing.

The issue happens when I initially load the website.

  1. I resize into the 860px breakpoint, and toggle the nav. All works fine and as expected.
  2. Then I resize past 860px.
  3. And once again I resize back into the 860px enquire.js media query. The toggle nav outputs both console messages.

Any ideas?

   enquire.register("screen and (max-width:860px)", {

        match : function()
        {   
            nav_wrapper.removeClass('show').addClass('hide');

            nav_toggle.click(function()
            {
                if((nav_wrapper).hasClass('hide'))
                {
                    console.log('It\'s hidden');
                    nav_wrapper.removeClass('hide').addClass('show');
                }
                else
                {
                    console.log('It\'s opened up');
                    nav_wrapper.removeClass('show').addClass('hide');
                }

            });

        },

        unmatch : function()
        {
            nav_wrapper.removeClass('hide').addClass('show');
        },

    });

Source: (StackOverflow)

jQuery append not inserting detached elements

I can't seem to get append working for elements I am detaching with detach()

Basically what I want to do is remove some images from the DOM based on screen size (larger than 900px) and add them back (smaller than 900px). I am using enquire.js to handle the breakpoints but I am unable to properly implement the insertion of the removed elements.

Here's the html:

<div class="mobile-slides">
  <a><img src="image.jpg" /></a>
  <a><img src="image2.jpg" /></a>
  <a><img src="image2.jpg" /></a>
</div>      

Here's the js I'm using:

enquire.register("screen and (min-width: 900px)", {
    match : function() {
        var slides = $('.mobile-slides a').detach();
    },
    unmatch : function() {
        $('.mobile-slides').append(slides);
    }
});

Detach seems to be working but when the second condition is met nothing is happening. Am I doing something wrong?

EDIT Stupid mistake on my behalf I was only declaring the variable "slides" inside the enquire match function therefore it wasn't available to the unmatch function.

This now works:

var slides = $('.mobile-slides a');
enquire.register("screen and (min-width: 900px)", {
    match : function() {
        $('.mobile-slides a').detach();
    },
    unmatch : function() {
        $('.mobile-slides').append(slides);
    }
});

I could also use remove() it seems instead of detach()


Source: (StackOverflow)

Object does not support property or method attachEvent

i use library enquire.js, good library, but have some problem, in ie8. console have message "Object does not support property or method addListener" in file enquire.js, ok, use google and found solution:

if("addEventListener" in this.mql) {
        this.mql.addListener(this.listener);
    } else {
        this.mql.attachEvent('onclick', function(){
            console.log('ssss');
            this.listener;
    });
}

ok, now, i have message "Object does not support property or method attachEvent". Any ideas?


Source: (StackOverflow)

Moving responsive element - clone or duplicate

I have an element and as part of the responsive design it has to move to a different section on my page.

As I see it I have 2 solutions

(i) have a duplicate element and use visibility in css.

(ii) use enquire.js and move the element.

Option 1 is the easier but is there a problem having duplicate markup to achieve this task? I am sure someone will tel me if an element has to move the deisgn is flawed, however I did not design the site. Any thoughts on best practice would be appreciated. On a really clean solution would be great.


Source: (StackOverflow)

Difference between matchmedia and enquire js

First of all, I would like to highlight that I am quite a newbie in javascript programming and am trying to learn as much as I can from here. Reading the enquire js api, documentations as well as the sourcecode. I would like to know what is the difference between enquire js and the conventional using matchmedia and resize event listeners.

Link to enquire js:http://wicky.nillia.ms/enquire.js/

Would appreciate any contribution


Source: (StackOverflow)

Turning scripts off and on based on Media Queries?

I am using a widget in my layout and I have it now so when a certain breakpoint is hit it will not display that larger widget and then goes to the smaller one. The larger widget does hide and the smaller one shows up but the text that is associated with both isn't right.

The text for the large widget displays and the smaller text for the small widget doesn't. I am pretty sure it has to do with the scripts each are using. The display none does hide the elements but the scripts seem to be still running.

I have absolutely no clue about JavaScript yet and would prefer a HTML or CSS answer if possible. If not then I will go with JS but will need some direction please. I have read numerous articles and even in the process of learning JS but still not sure how some of what I've read applies.

@media all and (max-width: 900px) {
  // styles
}

if (document.documentElement.clientWidth < 900) {
  // scripts
}

This is what I've found that seems like it is what I need but I'm not sure on the syntax of how to call the script I need. Do I just put the script itself in there without any other information? I have also read about using jquery to do this with something like this

$(window).resize(function() {
if ($(this).width() > 480) {
  // call supersize method
}
});

And I've even read about using Modernizer to do this but I still have to go through the documentation.

In the bin it doesn't show any of the text at all but the larger text is there and off to the side of the small widget. I just need to shut that large script off and turn the other on at a certain media query.

Any help is greatly appreciated.

HTML

  <aside class="smallScreen">
      <div class="smallWeather" style='width: 200px; height: 440px; background-image:
  url(http://vortex.accuweather.com/adcbin/netweather_v2/backgrounds/red_500x440_bg.jpg
  ); background-repeat: no-repeat; background-color: #993333;' ><div 
  id='NetweatherContainer' style='height: 420px;' ><script src='http://...'></script>  
  </div></div></aside>
  </div></div></div></aside>


  <aside class="largeScreen">
      <div class="largeWeather" style='width: 500px; height: 440px; background-image:
  url(http://vortex.accuweather.com/adcbin/netweather_v2/backgrounds/red_500x440_bg.jpg
  ); background-repeat: no-repeat; background-color: #993333;' ><div 
  id='NetweatherContainer' style='height: 420px;' ><script src='http://...'></script>  
  </div></div></aside> 

CSS

  @media screen and (min-width: 564px) and (max-width: 604px) {
  .largeScreen {
display: none;
}

  .smallScreen {
display: block; 
width: 55%;
min-width: 240px;
height: 100%;
font-size: 0;
margin-left: auto;
margin-right: auto;
margin-bottom: 1.2rem;
}

  .smallWeather {
position: relative;
display: block;
width: 240px;
height: 420px;  
background: white;
margin-left: auto;
margin-right: auto;
}

What is the best way to do this and why please? Is jQuery the best way from a mobile performance standpoint?

UPDATE: Going to use enquire.js because of it's straightforward approach (although I'm still a bit sketchy on it's use) and how small it is.

This is the basic code:

enquire.register("screen and (max-width: 605px)", {

// OPTIONAL
// If supplied, triggered when a media query matches.
match : function() {},      

// OPTIONAL
// If supplied, triggered when the media query transitions 
// *from a matched state to an unmatched state*.
unmatch : function() {},    

// OPTIONAL
// If supplied, triggered once, when the handler is registered.
setup : function() {},    

// OPTIONAL, defaults to false
// If set to true, defers execution of the setup function 
// until the first time the media query is matched
deferSetup : true,

// OPTIONAL
// If supplied, triggered when handler is unregistered. 
// Place cleanup code here
destroy : function() {}

});

Still not done and looking for more support with this. Now that I've chose this route, I see that there is quite a few articles and questions already about enquire.js. I will update my situation as I read up.

UPDATE: This is where I'm at but it's not working yet. I have the styles associated with each script still in the HTML and display none used accordingly. Will doing this work once I get the enquire.js correct?

Here is the new jsbin

Thanks again for everything!!


Source: (StackOverflow)

Orientation change issue in iOS7 iPad with enquire.js

This is only occurring on iPad iOS7. Works perfectly on iOS6

When I open the page on Portrait, topProducts.produtSliderEnable(); and topProducts.tabletThreeItems(); functions had been called.

But

When I open the page on Landscape, then I change to Portrait, nothing is called. Only when I do a click event on a element that belongs to a function I showed below, then both is called

enquire.register("(min-width: 768px) and (max-width: 979px)", {
    match : function() {
        topProducts.produtSliderEnable();
        topProducts.tabletThreeItems();
    },
    unmatch : function() {
        topProducts.productSliderDisable();
    }
});

I have no clue why this is happening. Many thanks for any response.

==========================================

Functions if you want to look further, snipped out from my Literal Object

    produtSliderEnable: function () {
        if ($('.product-block .product-item').length === 4) {

            nextToggle.show();

            prevToggle.on('click', function () {
                $(this).hide();
                nextToggle.show();

                container.animate({
                    left: "0"
                });

                productItem.removeClass('active');
                productDetails.removeClass('active');
            });

            nextToggle.on('click', function () {
                $(this).hide();
                prevToggle.show();

                container.animate({
                    left: "-203px"
                });

                productItem.removeClass('active');
                productDetails.removeClass('active');
            });

            topProducts.swipeToggle();
        }
    },
    productSliderDisable: function() {
        if ($('.product-block .product-item').length === 4) {

            nextToggle.hide().unbind();
            prevToggle.hide().unbind();

            container.css({
                'left' : '0'
            });
        }
        $('.product-block').attr('id', '');
    },
    tabletThreeItems: function() {
        if (productItem.length === 3) {
            $('.product-block').attr('id', 'threeItems');
        }
    }

Source: (StackOverflow)

Move element back to original position

I am using the enquire.js plugin to parse media queries stored as data-attributes which move the elements position in the DOM based on the browser width.

So I have wrote the following which works fine when you manually specify the unmatch, the problem is from the auto. I want this to remember the original position and automatically move the element back when it falls outside of the media query.

But I am having issues where the prev/next element that was originally references has also moved. Is there another way that I can move the element back to its original position? Or am I better off just hiding the element instead of moving it?

/*
 * Organise elements using meta data
 * 
 * @example:
 * data-respond='{
 *      "query":"screen and (max-width:481px)", 
 *      "match": { 
 *          "target": "#page", 
 *          "method": "appendTo"
 *      }, 
 *      "unmatch":{
 *          "target": "#footer", 
 *          "method": "appendTo"
 *      }
 * }'
 */
var $this,
data,
options,
allowedMethods = ['appendTo', 'prependTo', 'insertAfter', 'insertBefore'];

$("[data-respond]").each(function () {
    $this = $(this),
    data = $this.data("respond");
    options = {};

    // check we have object
    /*if(typeof data !== 'object'){
        data = eval(data);
    }*/

    if (data.match) {
        if ($.inArray(data.match.method, allowedMethods) > -1) {
            options.match = function () {
                if (data.match.method == 'insertAfter') {
                    if ($this[0] == $(data.match.target).next()[0]) {
                        return;
                    }
                }
                if ($(data.match.target).length) {
                    $this[data.match.method](data.match.target);
                }
            }
        }
    } //match

    if (data.unmatch) {
        if (data.unmatch == 'auto') {
            data.unmatch = {};

            // a) insert after                      
            if ($this.prev().length) {
                data.unmatch.target = $this.prev();
                data.unmatch.method = 'insertAfter';
            } else if ($this.next().length) {
                // c) insert before 
                data.unmatch.target = $this.next();
                data.unmatch.method = 'insertBefore';
            } else {
                // d) append to parent
                data.unmatch.target = $this.parent();
                data.unmatch.method = 'appendTo';
            }

            if ($.inArray(data.unmatch.method, allowedMethods) > -1) {
                options.unmatch = function () {
                    $this[data.unmatch.method](data.unmatch.target);
                }
            }
        } else {
            // Manually set unmatch
            if ($.inArray(data.unmatch.method, allowedMethods) > -1) {
                options.unmatch = function () {
                    if ($(data.unmatch.target).length) {
                        $this[data.unmatch.method](data.unmatch.target);
                    }
                }
            }
        }

    } //unmatch

    enquire.register(data.query, options);
});

Jsbin - http://jsbin.com/akAV/1/edit


Source: (StackOverflow)

How to use Enquire.Js?

Enquire.js is a Javascipt that re-creates CSS media queries for Javascripts. This means you can wrap your Javascripts in Media Queries. (Just like you would wrap CSS in Media Queries).

I'm not quite sure how to use it. This tutorial says this:

enquire.register("max-width: 960px", function() {
  // put your code here
});

However, when I follow that, my code stops working.

Here is an example of some Jquery Tabs without Enquire.JS. It works fine.

Here are the same tabs, but with Enquire.JS added. Now it stops working.

I've experimented with different variations of the code, but none of them work. What am I doing wrong?

I think you might have place the Jquery Tab code in a separate file and then link to that file from within Enquire.Js, but I'm not sure how you would do that. (Although it would be handy to know as I'd imagine it would let you keep your scripts be more reusable).

PS. This is not a criticism of Enquire.Js. I know that the problem lies squarely with my lack of proficiency in Javascript! I did spend a couple of hours searching for a solution, but couldn't find anything.

Thanks for any help!


Source: (StackOverflow)