I'm working on an assignment for a class where I have to make an external JavaScript file that checks a page's current width and changes the linked CSS style based on it, and have that occur whenever the page loads or is resized. Normally, we are given an example to base our assignment off of, but that was not the case this time around.
Essentially we are to use an if...then statement to change the style. I have no clue what the appropriate statements would be for the function. I've looked around and the potential solutions are either too advanced for the class or don't go over what I need. As far as I know I cannot use jQuery or CSS queries.
If someone could give me an example of how I would write this out, I would be very appreciative.
Try this code
html is
<div id="resize" style="background:red; height: 100px; width: 100px;"></div>
javascript is
var resize = document.getElementById('resize');
window.onresize=function(){
if(window.innerWidth <= 500) {
resize.style = "background:blue; height: 100px; width: 100px;";
}
else {
resize.style = "background:red; height: 100px; width: 100px;";
}
};
i have create a sample for you look at here TESTRESIZE
try resizing your browser and let me know if it is what you are looking for.
//Use This//
function adjustStyle() {
var width = 0;
// get the width.. more cross-browser issues
if (window.innerHeight) {
width = window.innerWidth;
} else if (document.documentElement && document.documentElement.clientHeight) {
width = document.documentElement.clientWidth;
} else if (document.body) {
width = document.body.clientWidth;
}
// now we should have it
if (width < 799) {
document.getElementById("CSS").setAttribute("href", "http://carrasquilla.faculty.asu.edu/GIT237/smallStyle.css");
} else {
document.getElementById("CSS").setAttribute("href", "http://carrasquilla.faculty.asu.edu/GIT237/largeStyle.css");
}
}
// now call it when the window is resized.
window.onresize = function () {
adjustStyle();
};
window.onload = function () {
adjustStyle();
};
Use CSS and media queries. It's bad idea to change style by js.
Related
I'm following a guide that allows Google Map screen to disable scrolling depending on the screen size. The only part i'm struggling is to write a code that dynamically changes the True/False value when i resize the screen manually.
This is the website that I followed the instruction but I can't seem to write the correct syntax code to produce the dynamic true false value depending on the screen size https://coderwall.com/p/pgm8xa/disable-google-maps-scrolling-on-mobile-layout
Part of the code that i need to use:
$(window).resize()
And then:
setOptions()
So I'm struggling to combine them together.
I have tried something like this:
var dragging = $(window).width(function resize() {
if (dragging > 560) {
return true;
} else {
return false;
}
});
The article you linked to is lacking important information as it fails to mention that $ is (presumably) jQuery. But you don't need jQuery at all.
What you can use instead is the MediaQueryList. It is similar to media queries in CSS, but it is a JavaScript API.
The following is an untested example of how you might use it with a MediaQueryList event listener. It sets the initial value and listens to changes to your media query with a handler that uses setOptions from the Google Maps API.
var mql = window.matchMedia('(min-width: 560px)');
var isDraggable = mql.matches;
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
draggable: isDraggable
});
}
function mqChange(e) {
map.setOptions({draggable: !!e.matches});
}
mql.addListener(mqChange);
You could add an event listener to the resize event and set a value of your variable whenever the size of the window is changed:
var dragging = false;
window.addEventListener('resize', function(event) {
dragging = window.innerWidth > 560;
});
Since you mentioned that you want to disable scrolling when the windows size extends a certain value, it might be easier to just do this. If you try it you can see in the console that the value changes whenever you resize your window):
window.addEventListener('resize', function(event) {
console.log(window.innerWidth);
if (window.innerWidth > 560) {
// disable scrolling or do whatever you want to do
}
});
BTW, in your code you do this:
if (dragging > 560) {
return true;
} else {
return false;
}
You can simplify this to:
return dragging > 560
Which is exactly the same.
You can use this function to get the width and height on a resize of the screen.
$(window).resize(function() {
$windowWidth = $(window).width();
$windowHeight = $(window).height();
// run other functions or code
});
But, if you want to only show/hide a html element based on the screen size, you can also use plain html/css.
<div id="maps"></div>
Css:
#media only screen and (max-width: 560px) {
#maps {
display: none;
}
}
you can use the matchMedia function to run a callback whenever the media query status is changing
var mql = window.matchMedia('(min-width: 700px)');
function mediaHandler(e) {
if (e.matches) {
/* the viewport is more than 700 pixels wide */
} else {
/* the viewport is 700 pixels wide or less */
}
}
mql.addListener(mediaHandler);
hoping to get some JS/CSS help here. I need to have the checkout button on a page of mine go to the top of the page and become fixed if the user can no longer see it scrolling down the page in mobile view. I'm hoping someone can help! The one thing messing me up is that I can't use jQuery
![function checkoutScroll() {
var button = document.querySelector('.cartSidebar__checkoutButton');
window.addEventListener('scroll', function () {
var distanceFromTop = document.body.scrollTop;
if (distanceFromTop === 0) {
button.style.position = 'static';
button.style.top = 'auto';
}
if (distanceFromTop > 0) {
button.style.position = 'fixed';
button.style.top = '0px';
}
});
}
What you are trying to achieve can be done through CSS which would make more sense as it's a visual / UI task. I would add top margin equivalent to the css height of your button and leave it as fixed top. As a benefit, you would be able to take advantage of the media queries to limit the CSS rules to the mobile view.
#media screen and (max-width: 960px) {
.container{
margin: 3em;
}
.checkout_button{
display:block;
position:fixed;
top:0;
left:0;
width:100%;
}
}
something very simple like https://jsfiddle.net/f19Lus43/
If you want to stay in javascript for some obscure reasons ( I can't say compatibility because of document.querySelector is working only on evolved browser ) it's up to you but having an example of your code would help us respond :)
So I take it you want the function to only run on smaller screens/browser viewports? Is that what you mean by "mobile view"? I've been using this for a while. Not sure if its better than Glen's solution but it's worked for me without fault. First we define our functions:
function updateViewportDimensions() {
var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName('body')[0],x=w.innerWidth||e.clientWidth||g.clientWidth,y=w.innerHeight||e.clientHeight||g.clientHeight;
return { width:x,height:y };
}
// setting the viewport width
var viewport = updateViewportDimensions();
function detectMob() {
viewport = updateViewportDimensions();
if (viewport.width <= 768) {
return true;
} else {
return false;
}
}
Then every time you need to check if the size of the viewport is less than 768 pixels wide you do:
if (detectMob){
//your code here
}
I want to change the order of elements in the DOM based on different browser sizes.
I've looked into using intention.js but feel that it might be overkill for what I need (it depends on underscore.js).
So, i'm considering using jQuery's .resize(), but want to know if you think something like the following would be acceptable, and in line with best practices...
var layout = 'desktop';
$( window ).resize(function() {
var ww = $( window ).width();
if(ww<=767 && layout !== 'mobile'){
layout = 'mobile';
// Do something here
}else if((ww>767 && ww<=1023) && layout !== 'tablet'){
layout = 'tablet';
// Do something here
}else if(ww>1023 && layout !== 'desktop'){
layout = 'desktop';
// Do something here
}
}).trigger('resize');
I'm storing the current layout in the layout variable so as to only trigger the functions when the window enters the next breakpoint.
Media queries are generally preferred. However, if I am in a situation where I am in a single page application that has a lot of manipulation during runtime, I will use onresize() instead. Javascript gives you a bit more freedom to work with dynamically setting breakpoints (especially if you are moving elements around inside the DOM tree with stuff like append()). The setup you have is pretty close to the one I use:
function setWidthBreakpoints(windowWidth) {
if (windowWidth >= 1200) {
newWinWidth = 'lg';
} else if (windowWidth >= 992) {
newWinWidth = 'md';
} else if (windowWidth >= 768) {
newWinWidth = 'sm';
} else {
newWinWidth = 'xs';
}
}
window.onresize = function () {
setWidthBreakpoints($(this).width());
if (newWinWidth !== winWidth) {
onSizeChange();
winWidth = newWinWidth;
}
};
function onSizeChange() {
// do some size changing events here.
}
The one thing that you have not included that is considered best practice is a debouncing function, such as the one below provided by Paul Irish, which prevents repeated firing of the resize event in a browser window:
(function($,sr){
// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');
// usage:
$(window).smartresize(function(){
// code that takes it easy...
});
So incorporate a debouncer into your resize function and you should be golden.
In the practice is better to use Media Queries
Try this, I'm in a hurry atm and will refactor later.
SCSS:
body, html, .wrapper { width: 100%; height: 100% }
.sidebar { width: 20%; height: 500px; float: left;
&.mobile { display: none } }
.content { float: right; width: 80% }
.red { background-color: red }
.blue { background-color: blue }
.green { background-color: green }
#media all and (max-width: 700px) {
.content { width: 100%; float: left }
.sidebar { display: none
&.mobile { display: block; width: 100% }
}
}
HAML
.wrapper
.sidebar.blue
.content.red
.content.green
.sidebar.mobile.blue
On 700 px page breaks, sidebar disappears and mobile sidebar appears.
This can be much more elegant but you get the picture.
Only possible downside to this approach is duplication of sidebar.
That's it, no JS.
Ok, the reason for my original question was because I couldn't find a way to move a left sidebar (which appears first in the HTML) to appear after the content on mobiles.
Despite the comments, I still can't see how using media queries and position or display alone would reliably solve the problem (perhaps someone can give an example?).
But, it did lead me to investigate the flexbox model - display: flex, and so I have ended up using that, and specifically flex's order property to re-arrange the order of the sidebars and content area.
Good guide here - https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Situation:
I'm working on a responsive design that involves the typical HTML/CSS combo. Everything is working nicely except in one case where there is an iframe inside of a div. The iframe should adjust automatically to the size of the parent div. A purely css solution has not presented itself so I'm going with a JQuery approach. It works nicely except in one scenario, when resizing from a smaller width to a larger width screen.
HTML:
<div class="container">
<iframe class="iframe-class" src="http://www.cnn.com/"></iframe>
</div>
CSS:
.container {
width: 100%;
height: 250px;
}
.iframe-class {
width: 100%;
height: 100%;
border: 1px solid red;
overflow: auto;
}
Javascript:
$(function () {
setIFrameSize();
$(window).resize(function () {
setIFrameSize();
});
});
function setIFrameSize() {
var ogWidth = 700;
var ogHeight = 600;
var ogRatio = ogWidth / ogHeight;
var windowWidth = $(window).width();
if (windowWidth < 480) {
var parentDivWidth = $(".iframe-class").parent().width();
var newHeight = (parentDivWidth / ogRatio);
$(".iframe-class").addClass("iframe-class-resize");
$(".iframe-class-resize").css("width", parentDivWidth);
$(".iframe-class-resize").css("height", newHeight);
} else {
// $(".iframe-class-resize").removeAttr("width");
// $(".iframe-class-resize").removeAttr("height");
$(".iframe-class").removeClass("iframe-class-resize");
}
}
http://jsfiddle.net/TBJ83/
Problem:
As the window is resized smaller, it continually checks the window width and once it hits < 480 px, the code adds a class called iframe-class-resize and sets the width and height to that class. As the window is resized larger, it removes the class once the size hits 480 px. The problem is that setting the width and height attributes adds them directly to the element and not the class itself. Therefore, removing the class does not remove the new width and heights. I tried to force removing the attributes using removeAttr() (commented out above) but that didn't work.
Anyone see where the code above went wrong? Or any suggestions on how to accomplish having a responsive iframe more effectively? The main things that are required are that the iframe has to be inside the <div></div> and the div may not necessarily have a width or height defined. Ideally, the parent div should have the width and height explicitly defined but the way this site is currently setup, that won't always be possible.
Additional:
In case the above wasn't clear enough, try the following to reproduce the issue:
Open up a browser on a desktop machine. I'm using Chrome on a Windows machine. Don't maximize the browser.
Open up the jsfiddle above (http://jsfiddle.net/TBJ83/). You'll notice that the iframe content spans the entire width of the Preview panel.
Manually resize the width down until the entire window is < 480px. At this point, the iframe content will be pretty tiny.
Manually resize the width back up until the entire window is >> 480px. The goal is to have that iframe content to regain the entire width of the Preview panel. Instead, the content is retaining the resized width and height since the .css() function applies css changes directly to elements rather than to the classes.
Thanks in advance!
You can do this in about 30 characters. Change:
$(".iframe-class").removeClass("iframe-class-resize")
to:
$(".iframe-class").removeClass("iframe-class-resize").css({ width : '', height : '' })
This will reset the width/height you applied to the element. When you use .css() you add whatever you pass-in to the style attribute of the element. When you pass a blank value, jQuery removes that property from the style attribute of the element.
Here is an updated fiddle: http://jsfiddle.net/TBJ83/3/
EDIT
OK, here's something tweaked for performance (and just some other ways to do things):
$(function () {
//setup these vars only once since they are static
var $myIFRAME = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
ogWidth = 700,
ogHeight = 600,
ogRatio = ogWidth / ogHeight,
windowWidth = 0,//store windowWidth here, this is just a different way to store this data
resizeTimer = null;
function setIFrameSize() {
if (windowWidth < 480) {
var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
newHeight = (parentDivWidth / ogRatio);
$myIFRAME.addClass("iframe-class-resize").css({ height : newHeight, width : parentDivWidth });
} else {
$myIFRAME.removeClass("iframe-class-resize").css({ width : '', height : '' });
}
}
$(window).resize(function () {
//only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
//this way you don't blow up someone's browser with your resize function running hundreds of times a second
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
//make sure to update windowWidth before calling resize function
windowWidth = $(window).width();
setIFrameSize();
}, 75);
}).trigger("click");//run this once initially, just a different way to initialize
});
This can be done using pure CSS as below:
iframe {
height: 300px;
width: 300px;
resize: both;
overflow: auto;
}
Set the height and width to the minimum size you want, it only seems to grow, not shrink.
This is how I would do it, code is much shorter: http://jsfiddle.net/TBJ83/2/
<div class="container">
<iframe id="myframe" src="http://www.cnn.com/"></iframe>
</div>
<script>
$(function () {
setIFrameSize();
$(window).resize(function () {
setIFrameSize();
});
});
function setIFrameSize() {
var parentDivWidth = $("#myframe").parent().width();
var parentDivHeight = $("#myframe").parent().height();
$("#myframe")[0].setAttribute("width", parentDivWidth);
$("#myframe")[0].setAttribute("height", parentDivHeight);
}
</script>
I did it that way for read-ability, but you could make it even shorter and faster...
function setIFrameSize() {
f = $("#myframe");
f[0].setAttribute("width", f.parent().width());
f[0].setAttribute("height", f.parent().height());
}
One selector, so you only look through the DOM once instead of multiple times.
For those using Prestashop, this is how I used the code.
In the cms.tpl file I added the below code:
{if $cms->id==2}
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
<script type="text/javascript" src='../themes/myheme/js/formj.js'></script>
<div style="width: 100%; height: 800px;">
<iframe style=" width: 100%; height: 100%; border: overflow: auto;" src="https://cnn.com"></iframe>
</div>
{/if}
Then created a new js file: formj.js and added the below code:
$(function () {
//setup these vars only once since they are static
var $myIFRAME = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
ogWidth = 970,
ogHeight = 800,
ogRatio = ogWidth / ogHeight,
windowWidth = 0,//store windowWidth here, this is just a different way to store this data
resizeTimer = null;
function setIFrameSize() {
if (windowWidth < 480) {
var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
newHeight = (parentDivWidth / ogRatio);
$myIFRAME.addClass("iframe-class-resize").css({ height : newHeight, width : parentDivWidth });
} else {
$myIFRAME.removeClass("iframe-class-resize").css({ width : '', height : '' });
}
}
$(window).resize(function () {
//only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
//this way you don't blow up someone's browser with your resize function running hundreds of times a second
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
//make sure to update windowWidth before calling resize function
windowWidth = $(window).width();
setIFrameSize();
}, 75);
}).trigger("click");//run this once initially, just a different way to initialize
});
In my CSS I have a media query like so:
#media (min-width: 800px) { /* styles */ }
And then in my jQuery, I'm targeting the window width and performing some actions.
Edit: as per the answers below, I have changed this function but my JS and CSS still didn't align. The problem was fixed by using the Modernizr function as specified in the accepted answer.
$(window).resize(function() {
var viewportWidth = $(window).width();
if (viewportWidth >= 800) {
// do something
}
});
The problem is that while the jQuery is executing bang on 800px or more, the CSS is kicking in at 740px.
Is there a known problem with these not aligning? Or could there be something on my page affecting the CSS and why it's 740px not 800px? Maybe there's something else I should be using instead of $(window)?
Edit: I've tested in Safari and it works perfectly. In Chrome and Firefox, the jQuery functions run spot on to 800px and so does the CSS. But in Chrome, the CSS actually runs after 740px, even though the media query is 800px - how can I get these to align perfectly?
You can use Modernizr to execute the media query in JS (the mq() method will return a boolean):
$(window).resize(function() {
if (Modernizr.mq('(min-width: 800px)')) {
// do something
}
});
Move your width check, or else the viewportWidth variable will always be the same thing:
$(window).resize(function() {
var viewportWidth = $(this).width();
if (viewportWidth >= 800) {
// do something
}
});
Valid code would be:
$(window).resize(function() {
var viewportWidth = $(window).width();
if (viewportWidth >= 800) {
// do something
}
});
Everytime window resizes the new value will be stored in viewportWidth variable. In your code viewportWidth gets the only value of the $(window).width() when the page was loaded.
What I just tried, and it seems to work, is to use the CSS media query to style an object, and then use javascript to test if the object has that style. Javascript is asking CSS what the answer is, rather than having two parts of the page determine it separately:
CSS:
#media (min-width: 800px) {
#viewType {width:3px;}
}
HTML :
<div id="viewType" style="display:none"></div>
JavaScript:
var answer = ($("#viewType").width()==3)
I agree with Steve answer. the jquery(window).width(); is does not match with the media queries and even doesn't provide accurate window width size. here is my answer taken from Steve and modified.
CSS :
#media (max-width: 767px) {
//define your class value, anything make sure it won't affect your layout styling
.open {
min-width: 1px !important;
}
}
.open {
min-width: 2px;
}
Js :
// when re-sizing the browser it will keep looking for the min-width size, if the media query is invoked the min-width size will be change.
$(window).on('resize orientation', function() {
var media = $('.open').css('min-width');
if( media == '1px') // means < 767px
{
// do your stuff
}
});
That's it~ hope it help.