Solved

Using JQuery with responsive design

Posted on 2013-11-20
17
685 Views
Last Modified: 2013-12-04
Hi,
I am building a respsonsive site and the more I seem build it up the more complex and unstable my JQuery is becoming.
I have one media query in my CSS to determine between my two states of desktop and mobile (mobile < 640px width)

One example of the issues I have is with some hide/show elements on the page.

I have a filter menu (not the navigation) that is always to be shown in desktop but needs to be collapsed in mobile. Therefore I have the CSS styles to make this happen, however when in mobile and the display filters button is clicked it needs to then show it - the jquery then creates an
inline style for the element overwriting any CSS styles set to it, therefore when the user then changes to desktop by making the viewport wider it is still in the state that the jquery last set it as (so if they hid it in mobile, it will still be hidden in desktop).

To overcome this I have added in a function that checks everytime the viewport width is changed via $(window).resize(function_name); so that if the window is in the desktop range it will automatically show(); the filter menu and vice versa for mobile.
This is fine, however it is moving me away from controlling the responsive design in the CSS and as I introduce more and more of these elements it becomes increasingly difficult to manage and is causing some issues.

One being, if the user changes from portrait to landscape in mobile it reads this as a viewport width change and therefore hides the filter menu even though they might have it open and be browsing it.

My more complex issues are with trying to unbind and bind 'onclick' functions etc depending on the viewport width too.

Do you have any suggestions as to how to approach this better or ways to tidy it up?

Example structure of my js:
var responsive = function () {
    $(document).ready(function () {
&#9;&#9;var pageType = $("#pageType");
        //Pages
        if (typeof pageType === 'object') {


            if (pageType.val() == "tour-results-page") {
                //trigger viewport resize check
                $(window).resize(tourResultScript);
                tourResultScript();
&#9;&#9;&#9;}
&#9;&#9;&#9;if (pageType.val() == "tour-details-page") {
                $(window).resize(tourDetailScript);
                tourDetailScript();
&#9;&#9;&#9;}
&#9;&#9;}
&#9;&#9;
&#9;&#9;function tourResultScript() {
            var windowsize = $(window).width();
&#9;&#9;&#9;
&#9;&#9;&#9;if (windowsize < 630) {
&#9;&#9;&#9;&#9;responsive.toggleContent.filter('.filter-open', '.filter-form', '.filter-open .arrow', '#sort-options', '.tour-sort .arrow');
&#9;&#9;&#9;} else {
&#9;&#9;&#9;&#9;responsive.toggleContent.unbindElement('.filter-open');
&#9;&#9;&#9;}
&#9;&#9;}
&#9;&#9;responsive.toggleContent = {
&#9;&#9;&#9;filter : function (activator, toggle, arrow, hide, other) {
&#9;&#9;&#9;&#9;$(activator).unbind('click').bind('click', function(e) {
&#9;&#9;&#9;&#9;&#9;$(hide).hide();
&#9;&#9;&#9;&#9;&#9;$(toggle).slideToggle(500, function(){
&#9;&#9;&#9;&#9;&#9;&#9;if($(this).is(':visible')){
&#9;&#9;&#9;&#9;&#9;&#9;&#9;
&#9;&#9;&#9;&#9;&#9;&#9;&#9;if ($(this).attr('id') == 'sort-options') {
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(arrow).css("background-image", "url(img/mobile-less-arrow.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(other).css("background-image", "url(img/mobile-more-arrow-white.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;} else {
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(arrow).css("background-image", "url(img/mobile-less-arrow-white.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(other).css("background-image", "url(img/mobile-more-arrow.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;}
&#9;&#9;&#9;&#9;&#9;&#9;} else {
&#9;&#9;&#9;&#9;&#9;&#9;&#9;if ($(this).attr('id') == 'sort-options') {
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(arrow).css("background-image", "url(img/mobile-more-arrow.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;} else {
&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$(arrow).css("background-image", "url(img/mobile-more-arrow-white.png)");
&#9;&#9;&#9;&#9;&#9;&#9;&#9;}
&#9;&#9;&#9;&#9;&#9;&#9;}
&#9;&#9;&#9;&#9;&#9;});
&#9;&#9;&#9;&#9;&#9;return false;
&#9;&#9;&#9;&#9;});
&#9;&#9;&#9;}
&#9;&#9;}
&#9;});
}

Open in new window


Thanks
0
Comment
Question by:Al4ddin2
  • 7
  • 4
  • 2
  • +1
17 Comments
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39662363
I would suggest starting from scratch, but use a library  like bootstrap http://getbootstrap.com/  I have more details on this here

http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/HTML/Q_28293862.html#a39648026

http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_28292934.html#a39644671

Below is sample code from bootstrap's grid that takes care of going from columns to stacked with mobile.  They have the media queries built in so you can just use classes.  It is much easier.  And yes, responsive does take a lot more thought for each page you layout.
<div class="row">
  <div class="col-xs-12 col-md-8">.col-xs-12 .col-md-8</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>

<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->
<div class="row">
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>

<!-- Columns are always 50% wide, on mobile and desktop -->
<div class="row">
  <div class="col-xs-6">.col-xs-6</div>
  <div class="col-xs-6">.col-xs-6</div>
</div>

Open in new window

0
 

Author Comment

by:Al4ddin2
ID: 39662451
Hi,

Thanks but its not the responsive layout side of it that i am struggling with.
I have based my website build on bootstrap and am using their grid system fine - the page looks great in both mobile and desktop - its more to do with handling the jquery side of it I am struggling with.

Thanks
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39662496
If you check out the bottom of the page http://getbootstrap.com/css/ you will see the table on how to make items visible or not based on the viewport.  Did you try that?

This is a sample http://jsbin.com/IKAbajOn/1/edit?html,output

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery.min.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap.css" rel="stylesheet" type="text/css" />
<script src="http://getbootstrap.com/dist/js/bootstrap.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
  <div class="visible-xs">XS</div>
  <div class="visible-sm">SM</div>
  <div class="visible-md">MD</div>
  <div class="visible-lg">LG</div>
  
</body>
</html>

Open in new window

0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:Al4ddin2
ID: 39662550
Sorry padas, I dont think you are understanding my issue.
I have things hiding and showing for mobile and desktop correctly.

I am using media queries and the bootstrap framework to help me and it is working fine.

The issue I am having, as stated in the initial request, is when I apply say a jquery onclick to a div class that has content collapsed for mobile (but shown in desktop) the CSS successfully collapses the div but when the user clicks on the div and the content then
displays, whilst in mobile, (toggle) the jquery will append an inline style of display:block to the element as it should, if the user was to click it again to collapse it (display: none) if they were then to change to a viewport of greater than 640px the div would still be
hidden as the inline style set by the jquery onclick would over-ride the CSS.

Does this make sense?
0
 

Author Comment

by:Al4ddin2
ID: 39665798
Can anyone assist? - Would you like me to post more of my JS?
Thanks
0
 

Author Comment

by:Al4ddin2
ID: 39675265
What is the industry standard for dealing with differences in jquery functions and toggling binding/unbinding them when building responsive sites?
Is there a better way then checking and firing the scripts as and when the viewport changes size?

Any advice would be very much appreciated.

Thanks
0
 
LVL 53

Expert Comment

by:COBOLdinosaur
ID: 39688194
You have made the biggest possible mistake you can make; allowing jquery to write inline styling.  That destroys the integrity of the CSS and breaks the the document object.

If you cannot handle all the effects you need with media queries (there is much more to them then just looking at screen size, then you need to define classes for the various states for elements, and limit the use of jquery presentation operations to changing the classes of elements.  

Under no circumstance should you use inline styles.  If you do that you will just end up adding hack on top of hack on top of hack until the whole thing collapses into a pile of rubble.

you might want to take a look at all the options available in media queries from a professional source here.

Cd&
0
 
LVL 42

Accepted Solution

by:
David S. earned 500 total points
ID: 39688576
Al4ddin2, I'm not aware of any industry standard for dealing with this. Responsive web design has not been widely used for very long. Keeping paths to background-images that are just static strings in a script seems like a bad idea. Besides the conflict you mentioned, such a practice violates the principle of "separation of concerns".  It's much better to move those to your stylesheet, each with a different class.

Cd&, even if he wasn't using inline styles directly, several jQuery methods including hide, slideUp, and slideDown use inline styles to work. Callback functions can be used with such jQuery methods to remove the inline style(s), especially for the "display" property, and add a class. In the case of the hide method, which isn't an animation method, it can be simply replaced with class switching. Also you might consider avoiding the aforementioned methods in jQuery and use CSS3 transitions with class switching instead where you want an animation to occur.

Oh, how I wish we could have named breakpoints that are specified in a stylesheet to make it easier to not have to specify window dimensions in scripts.
0
 

Author Comment

by:Al4ddin2
ID: 39689411
Thanks Kravimir. Yes that is correct, there are certain JQuery methods that will always apply inline styles so it's not like I am applying directly myself. But as for the image paths and maybe even hide/show, thanks for the advice, I will change them to addClass instead and apply the styles in my CSS instead.
Is there a better way than checking the window.width on resize though? Or is that really the only way to detect changes?

Thank you for the information though, it is very interesting and beneficial.
0
 
LVL 42

Expert Comment

by:David S.
ID: 39690217
You're welcome.

I use ".is(':hidden')" sometimes, for example to check if the non-mobile main navigation is visible or not. "window.matchMedia()" can also be used to directly test media queries with JavaScript, but IE9 and older don't support it.
0
 
LVL 53

Expert Comment

by:COBOLdinosaur
ID: 39690798
The fact that a lot of jquery libraries use inline styles is one of the reasons I only use jquery as a last resort.  

When it come to CSS, most of what jquery does is make what would be a 30 second change to a stylesheet into a week long journey to the depths of hades trying to figure out what the author did to prevent a simple change.

 There is very little That jquery can do that I cannot do better myself using technology that does not break the Document Object, limit options, and add substanstial time for simple maintenance.  Plus I can rely on standards based technology, as opposed to the chaos of "anything goes" with jquery.

Cd&
0
 

Author Comment

by:Al4ddin2
ID: 39691969
Although your comment was helpful in seeing how good you are at other technologies, would you mind offering advice instead?
0
 
LVL 53

Expert Comment

by:COBOLdinosaur
ID: 39693046
would you mind offering advice instead?

I did.  You are just not interested in hearing anything that does not fit in with the self-limiting path you are on. You need to ask questions to figure out how to do some things.  I don't have to ask questions because I have already explored the range of technologies and know how to do things in the most efficient and sustainable way.  

I sometimes offer advice on professional development to my students and to users of other tech sites I support. Whether or not my advice gets followed does not make any difference to me; but I have managed to answer 7000+ questions here and several thousand on other sites, so sometimes I guess my advice is seen to have some value.

Cd&
0
 

Author Comment

by:Al4ddin2
ID: 39694752
I am sure you a a very wise person and knowledgeable in your subject areas, hence why you're on here answering queries.
My comment was not meant to offend but rather for you to let me know what some of these alternative technologies are that you would use before jquery. Rather than you just saying you would use 'them'.
As an example, how would you approach a scenario where you have an element that is hidden in mobile and not in desktop that when in mobile view has an on click event that adds a slide down transition but this needs removing for desktop. Happy to add this in a new thread if you wish for the points. Thank you b
0
 
LVL 53

Expert Comment

by:COBOLdinosaur
ID: 39696411
I don't need points.  I already have enough to sink an aircraft carrier.  

When you have differences in how rendering needs to be done on different devices then using media queries with alternate stylesheets will generally handle the differences with little or no scripting.  Even if the content presentation itself must be altered it can almost always be handled with media queries in the CSS.

Something as simple as different rendering for portrait and landscape orientation should never require anything more than a media query that responds to the change and switches to the alternate rendering.

It is simply a matter of showing the user only the elements appropriate for the conditions under which they are accessing, and hiding those things that are not appropriate.  That is what CSS is for.

Learn about media queries here:
https://developer.mozilla.org/en-US/docs/CSS/media_queries

Cd&
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Changing alignment and creating border 6 27
Fulfillment API php code sample 1 38
Changing Two Areas of a Page 5 16
Call Controller Action Method from ASPX 2 13
Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
How to build a simple, quick and effective accordion menu using just 15 lines of jQuery and 2 css classes
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question