Auto-resizing elements on window change (properly) - javascript

I'm making a JavaScript function that auto-resizes a div to same width/height of the window, when the window is resized.
The function is pretty basic, however I've noticed significant "paint" lag when the window is resized. In a JS fiddle, with no other elements on the page or other JavaScript, performance isn't really an issue. However in a real-world project, the lag is really annoying and something I'd like to fix.
I've iterated over a few different techniques but haven't really noticed much performance increase. Is there something I'm missing here? There must be a way to do this that's doesn't kill browser performance.
Here is the first function:
1.
window.onresize = function (event) {
var resize = document.querySelector(".resize");
var w = window.innerWidth;
resize.style.width = w + "px";
resize.style.height = w + "px";
};
This has pretty much the worst performance out of all - http://jsfiddle.net/SY5Tn/
2.
function resizer(e,w) {
e.style.width = w + "px";
e.style.height = w + "px";
}
window.onresize = setInterval(function() {
var e = document.querySelector(".resize");
var w = window.innerWidth;
resizer(e,w);
}, 100);
this has a little better performance. Not much difference though http://jsfiddle.net/SY5Tn/2/
3.
function resizer() {
var resizeLoop;
resizeLoop = setInterval(function() {
var e = document.querySelector(".resize");
var w = window.innerWidth;
e.style.width = w + "px";
e.style.height = w + "px";
}, 100);
function clear() {
clearInterval(resizeLoop);
}
window.onresize = function () {
resizeLoop();
}
document.addEventListener('mouseup', function() {
clear();
document.removeEvenetListener('mouseup');
});
}
resizer();
This was the best I could come up with, although I still get an error "number is not a function"
http://jsfiddle.net/SY5Tn/3/
Is there a better way of doing this? (no Jquery please);
P.S - I can't post this on Code Review as only have 1 rep point over there so it doesn't allow me to post multiple links.

Try this:
resizeLoop = function(){
setInterval(function() {
var e = document.querySelector(".resize");
var w = window.innerWidth;
e.style.width = w + "px";
e.style.height = w + "px";
}, 100);
}

You can solve this by pure CSS also using viewport units.
.resize {
width: 100vw;
}
You can check the support here..

you can add
.resize {
width: 100%;
height: 100%;
}

Related

Remove function on browser width

I'm still very new to javascript and I'm learning as I build. This may be a simple fix but how would I disable a function on my parallax images ( or disable a specific js function in general ) on a smaller width?
Here's what I have so far that doesn't quite work but shows "undefined". I've been searching for a solution for a couple of days now with no luck. Any help would be appreciated.
var paraLlaxS = document.querySelector("#firstImgc2");
var paraLlaxS = document.querySelector("#secondImgc2");
var paraLlaxS = document.querySelector("#backbox1");
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + ", " + yPos + "px, 0)";
}
window.addEventListener("DOMContentLoaded", scrollLoop, false);
var xScrollPosition;
var yScrollPosition;
function scrollLoop() {
xScrollPosition = window.scrollX;
yScrollPosition = window.scrollY;
setTranslate(0, yScrollPosition * -0.2, firstImgc2);
setTranslate(0, yScrollPosition * 0.15, secondImgc2);
setTranslate(0, yScrollPosition * -0.6, backbox1);
requestAnimationFrame(scrollLoop);
if(window.innerWidth < 900) {
document.querySelector('#firstImgc2').innerHTML = window.removeEventListener("DOMContentLoaded", scrollLoop, false);
return;
} else {
}
}
You could add a conditional return at the beginning of you function. But if the width increases again you would need to listen for that to start the loop again.
function scrollLoop() {
if(window.innerWidth < 900)return;
...
I borrowed a solution from another post.
Listen for browser width for responsive web design?
This code is compatible with a wider variety of browsers as getting the screen size can vary depending on the browser.
var width = 0;
function getWindowSize() {
if (document.body && document.body.offsetWidth) {
width = document.body.offsetWidth;
}
if (document.compatMode=='CSS1Compat' &&
document.documentElement &&
document.documentElement.offsetWidth ) {
width = document.documentElement.offsetWidth;
}
if (window.innerWidth) {
width = window.innerWidth;
}
return(width);
}

How do I change a HTML ID with Javascript on page load after getting window size?

I am wondering how I can use Javascript to get a windows size and then set (really clear) an HTML ID with it.
I am currently working on a site that has a "default" navigation ID of "access" which I want to blank out if the windows size is less than 800 px wide.
This is the page I am working on and if the ID is cleared I can then setup the mobile navigation to work with bootstrap.
`window.onload = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
window.onload = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
window.onresize = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
Use
var w = window.innerWidth;
to get the width of the page.
and then,
window.onload = function() {
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
You probably want to add this functionality in resize too.
EDIT: put the code in window.onload
Based on the comment,
window.onload = function() {
var accessElem = document.getElementById('access');
var updateAccess = function() {
var w = window.innerWidth;
if(w < 800) {
accessElem.removeAttribute('id');
}
else {
accessElem.setAttribute('id', 'access');
}
};
window.onresize = updateAccess; // call updateAccess on resize
updateAccess(); // call once on load to set it.
};
Also, in my opinion, adding/removing id is not a great idea.

Efficiently creating a simple parallax effect with jQuery

So for one of my new projects, I decided to write a super simple parallax script for some background images on scroll. This is what I came up with:
$(document).ready(function(){
parallaxScroll();
$(window).bind('scroll', function() {
parallaxScroll();
});
});
function parallaxScroll() {
$(".parallax").each(function() {
if($(this).hasClass('reverse')) {
$(this).css("background-position","center " + (($(this).offset().top - $(window).scrollTop())/2) + "px");
} else {
$(this).css("background-position","center " + (($(this).offset().top - $(window).scrollTop())/-2) + "px");
}
});
}
My question is, is this efficient enough? If not, is there a better solution? I wasn't sure if using an .each() would be best for performance, but it seems to work fine. The reason I have the function run at document load is so when you scroll the page for the first time, the background image doesn't jump.
Instead of css which sets the value immediately, consider using animate instead. It defers setting values using timers/requestAnimationFrame, ensuring that your animation does not block the UI, is async (runs pseudo-parallel to other code), and ensures that the animation is smooth.
This is a plain JS solution, but you'll be able to port it to jQuery really easily:
var lastScrollY = 0;
var backgroundImageY = 0;
var requestAnimationFrame = window.requestAnimationFrame ||
window.msRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame;
window.addEventListener('load', processScrollEvent);
function processScrollEvent() {
var innerHeight = window.innerHeight;
var scrollHeight = document.body.scrollHeight;
var backgroundImage = document.querySelector('#background img');
lastScrollY = document.body.scrollTop;
var currBackgroundImageY = Math.round(((backgroundImage.scrollHeight - innerHeight) / 100) * ((lastScrollY / (innerHeight - scrollHeight)) * 100));
if(currBackgroundImageY != backgroundImageY) {
backgroundImageY = currBackgroundImageY;
requestAnimationFrame(processScrollAnimationFrame);
}
}
function processScrollAnimationFrame() {
var backgroundImage = document.querySelector('#background img');
var transforms = ['transform', 'oTransform', 'msTransform', 'mozTransform', 'webkitTransform'];
for(var i = 0; i < transforms.length; i++) {
backgroundImage.style[transforms[i]] = 'translate3d(0, ' + backgroundImageY + 'px, 0)';
}
}

jquery function doesn't trigger

My resizeAreas function doesn't trigger in $(document).ready function. Here's the link to the app. I have also tried $(document).load but same result.
This problem is not consistent. But most of the time the page doesn't load correctly. If the list of task have the same height and 4 equal(as height) lists on the row then they are loaded correctly else they're not. To make sure that you see how it must look you can move a task element from one list to another. I don't have the reputation to post images.
Here is most of the javascript code:
function makeDropArea() {
var widthArea = $(".taskListing").width() / 2 - 55;
var heightArea = $(".taskListing").height();
$('.dropArea').width(widthArea);
$('.dropArea').css('margin-left', 5 + 'px');
$('.generalInfo').css('margin-left', 5 + 'px');
$('.generalInfo').css('width', widthArea * 2 + 220 - 45);
$('.subTaskHeader').css('width', widthArea + 25);
}
function makeDropElement(){
var widthEl = $('.dropArea').width() + 25 ;
$('.task').width(widthEl);
}
function taskListingSize(){
var width = getWidth();
var height = getHeight() * 80 / 100;
$('.taskListing').css('width', width);
}
function resizeAreas() {
$('.taskListing').each(function(){
var highestBox = 0;
$('.dropArea', this).each(function(){
if($(this).height() > highestBox)
highestBox = $(this).height();
});
$('.dropArea',this).css('min-height', highestBox);
});
}
$(document).ready(function () {
menu();
taskListingSize();
makeDropArea();
makeDropElement();
resizeAreas(); //<-- this is the one with the problems
$(".dropArea").resize(resizeAreas());
$( window ).resize(function() {
taskListingSize();
makeDropArea();
makeDropElement();
});
});
Thanks.
Update 1:
I've done some more testing and this bug is only on chrome and firefox but not on IE. The problem appears only on the openshift platform.
Either change:
$(".dropArea").resize(resizeAreas());
To:
$(".dropArea").resize("resizeAreas");
Or:
$(".dropArea").resize(function(){
resizeAreas();
});
I think it should be
$(".dropArea").resize(resizeAreas);
Or
$(".dropArea").resize(function(){
resizeAreas();
});

Issue with Image movement on mousemove (in opposite direction)

I have to move an image using jQuery / Javascript exactly like this url
I have done similar to this using my own logic. But it gets cut for smaller / bigger image either at the top or at the bottom. Or It moves completely at the bottom and doesn't move completely at the top or vice-versa.
http://jsfiddle.net/N2k6M/
(Please move the horizontal scrollbar to view full image.)
Can anyone please suggest me / Fix my code here, so that my mousemove functionality works perfectly fine and upper / lower part of image moves properly.
I need a seamless movement of image just like in the original url.
HTML PART
<div id="oheight" style="z-index:1000;position:absolute;">123</div> , <div id="yheight" style="z-index:1000;position:absolute;">123</div>
<img id="avatar" src="http://chaikenclothing.com/wp-content/uploads/2012/05/11.jpg![enter image description here][2]" style="position:absolute;overflow:hidden;" />
JAVASCRIPT PART
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script lang="javascript">
var doc_height = $(document).height();
function updateAvatarPosition( e )
{
var avatar = document.getElementById("avatar");
var yheight = parseInt(e.y);
var ywidth = e.x;
//avatar.style.left = e.x + "px";
if((yheight)<(doc_height)){
yheight*=2;
avatar.style.top = '-'+(yheight) + "px";
}
console.log(yheight);
$("#oheight").html(doc_height);
$("#yheight").html(yheight);
/*if((ywidth)<(doc_height/6)){
avatar.style.top = '-'+e.x + "px";
}*/
}
document.getElementById("avatar").onmousemove = updateAvatarPosition;
</script>
see http://jsfiddle.net/N2k6M/7/
function updateAvatarPosition( e )
{
var img_height = $('#avatar').height();
var window_height = $(window).height();
var factor = (img_height - window_height) / window_height;
if(factor > 1) {
var avatar = document.getElementById("avatar");
var yheight = parseInt(e.clientY);
avatar.style.top = '-'+(yheight * factor) + "px";
}
}
#Felix's answer is great and works well, however it's doing more work than necessary. There are a few constants that do not need to be reassigned with every call. By setting these outside of the updateAvatarPosition function you can improve performance some.
var avatar = $('#avatar');
img_height = avatar.height(),
window_height = $(window).height();
function updateAvatarPosition( e )
{
var factor = (img_height - window_height) / window_height,
yheight = parseInt(e.clientY);
if (factor < 1) {
factor = 1;
}
avatar.css('top', -(yheight * factor));
}
avatar.on('mousemove', updateAvatarPosition);
​
Updated Fiddle
Avatar is referenced more than once so no need to traverse the DOM multiple times, especially multiple times within a constantly cycling event like mousemove. Make a variable reference to avatar outside of the function. The image_height and window_height are also constants and do not change, so there is no need to recalculate them every time as well. If there is the chance that they would change, reassignment should be handled by a resize event.
Would have replied/commented directly under #Felix's answer but apparently don't have enough influence yet. :-/
i think this is something you want
http://jsfiddle.net/N2k6M/6/
var doc_height = $(document).height();
function updateAvatarPosition( e )
{
var avatar = document.getElementById("avatar");
var yheight = parseInt(e.clientY);
var ywidth = e.clientX;
if((yheight)<(doc_height)){
yheight*=2;
avatar.style.top = '-'+(yheight) + "px";
}
/*if((ywidth)<(doc_height/6)){
avatar.style.top = '-'+e.x + "px";
}*/
}
document.getElementById("avatar").onmousemove = updateAvatarPosition;​

Categories