Link to home
Start Free TrialLog in
Avatar of Al4ddin2
Al4ddin2

asked on

Using JQuery with responsive design

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
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

I would suggest starting from scratch, but use a library  like bootstrap http://getbootstrap.com/  I have more details on this here

https://www.experts-exchange.com/questions/28293862/Creating-a-HTML-5-page-so-that-it-works-for-different-screens.html?anchorAnswerId=39648026#a39648026

https://www.experts-exchange.com/questions/28292934/HTML5-CSS3-with-tables.html?anchorAnswerId=39644671#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

Avatar of Al4ddin2
Al4ddin2

ASKER

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
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

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?
Can anyone assist? - Would you like me to post more of my JS?
Thanks
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
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&
ASKER CERTIFIED SOLUTION
Avatar of David S.
David S.
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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.
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&
Although your comment was helpful in seeing how good you are at other technologies, would you mind offering advice instead?
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&
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
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&