jQuery window.on resize not firing at the right time - javascript

$myWindow.on('resize', function(){
var $width = $myWindow.width();
if ($width > 870) {
console.log('hey im 870');
$('#the-team-wrapper .flex-content').empty();
ajax_results.done(function(data) {
// console.log(data.job_titles[3]);
var employee_job_titles;
function job_titles_display(jobtitle,ind){
if (jobtitle.job_titles[ind].length>1) {
var my_array = [];
for (var i = 0; i < jobtitle.job_titles[ind].length; i++){
my_array.push(jobtitle.job_titles[ind][i][0]['title']);
employee_job_titles = my_array.join(' | ');
}
}else {
var employee_job_titles;
employee_job_titles = jobtitle.job_titles[ind][0]['title'];
}
return employee_job_titles;
}
for (var i = 0; i < data.employee_info.length; i++) {
if(i%2 == 0){
$('#the-team-wrapper .flex-content').append('<div class="profile-parent"><div class="employee-profile-pic flex-item" data-id="'+data.employee_info[i]['id']+'"></div><div class="employee-bio-wrapper flex-item"><h2 data-id="'+data.employee_info[i]['id']+'">'+data.employee_info[i]['firstname']+" "+data.employee_info[i]['lastname']+'</h2><h3 data-id="'+data.employee_info[i]['id']+'">'+job_titles_display(data,i)+
'</h3><p class="employee-bio-text employee-bio-text-not-active">'+data.employee_info[i]['bio']+'</p></div><button type="button" class="bio-prev-butt-left">View '+data.employee_info[i]['firstname']+'\'s'+' Bio</button><div class="hide-bio-close-button-left">x</div></div>');
}else {
$('#the-team-wrapper .flex-content').append('<div class="profile-parent"><div class="employee-bio-wrapper flex-item"><h2 data-id="'+data.employee_info[i]['id']+'">'+data.employee_info[i]['firstname']+" "+data.employee_info[i]['lastname']+'</h2><h3 data-id="'+data.employee_info[i]['id']+'">'+job_titles_display(data,i)+'</h3 data-id="'+data.employee_info[i]['id']+
'"><p class="employee-bio-text employee-bio-text-not-active">'+data.employee_info[i]['bio']+'</p></div><div class="employee-profile-pic flex-item" data-id="'+data.employee_info[i]['id']+'"></div><button type="button" class="bio-prev-butt-right">View '+data.employee_info[i]['firstname']+'\'s'+' Bio</button><div class="hide-bio-close-button-right">x</div></div>');
}
var profile_pic_path = data.employee_info[i]['profile_pic'].split('\\').join('\\\\');
$("#the-team-wrapper .flex-content-wrapper .flex-content .employee-profile-pic:eq("+i+")").css({'background': 'url(_employee_pics/'+profile_pic_path+')','background-repeat': 'no-repeat','background-position': 'center', 'background-size': 'cover'});
}
});
}
I have this code, and it should fire when width is greater than 870, but instead it fires when width is greater than 970 on Opera, and when width is about 890 on Chrome. How can I fix this and get consistent results across browsers. Thanks in advance.

Are you using a CSS reset to neutralize the browser's default margin or padding on the <body> element?
Different browsers add different amounts of either padding or margin to the <body> of the page, which could explain why the function is triggered at different points in different browsers.

The problem is, the resize event fires at different times and rates depending on browser, CPU load, and how fast you actually do the resizing.
Test the following code in your browsers. When I do this in a clean browser at a reasonable rate of coverage the difference usually comes in within around 2px of the target.
(BTW, you'll see I am caching the jQuery selectors into variables. Not strictly necessary for this test, but you might be surprised to find out how many bugs I've fixed because coders have invoked uncached jQuery selectors willy-nilly in loops and other repetitive places throughout their code).
var $window = $(window);
$window.on('resize',function(){
var w = $window.width();
if (w > 1000) {
console.log( w );
} else {
console.log('nope: ' + w)
}
});

Related

Javascript doesn't work in firefox and IE/edge

I have a piece of code, that's changing my div background on mousescroll and it's working fine in Chrome and Opera, but it doesn't in Firefox and IE/Edge.
I have two divs, the inner one has a background image that is changing on scroll down, the outer one is simply bigger so there is space to scroll.
In Firefox and IE/Edge, the scroll or doesn't work either skips an image, sometimes even doesn't purceed to scrolling the rest of the content on the website.
http://jsfiddle.net/s6qrfo9n/1/
Any ideas why?
Here it is (and I know it's poorly written, but I'm new to javascript and it does the job):
$(document).ready(function(){
var numberofscroll = 0;
var lastScrollTop = 0;
$("#home").scroll(function(){
var st = $(this).scrollTop();
(st > lastScrollTop) ? numberofscroll++ : numberofscroll--;
console.log(numberofscroll);
console.log(lastScrollTop);
console.log(st);
if (numberofscroll<2){
change_background2(numberofscroll);
}
else if (numberofscroll<3){
change_background3(numberofscroll);
}
else if (numberofscroll<4){
change_background4(numberofscroll);
}
lastScrollTop = st;
});
function change_background2(numberofscroll){
var i;
for (i = 2; i <= 2; i++) {
$("#home").css("background-image","url('images/movie_" + i + ".jpg')");
}
}
function change_background3(numberofscroll){
var i;
for (i = 3; i <= 3; i++) {
$("#home").css("background-image","url('images/movie_" + i + ".jpg')");
}
}
function change_background4(numberofscroll){
var i;
for (i = 4; i <= 4; i++) {
$("#home").css("background-image","url('images/movie_" + i + ".jpg')");
}
}
});
The problem lies in the smooth scrolling feature of firefox and ie (see this question). This causes the jQuery scroll event to fire multiple times every time you scroll, thus the 'missing' images--they are being put in, but then they're replaced so fast you can't see them.
Unfortunately, since you can't disable the smooth scrolling feature on people's browsers, there isn't really a perfect solution to this. The best solution is to debounce your scroll event handler. There are many ways to implement a debounce (google it for some ideas). A simple one would be just toggling a boolean after a timeout and checking it every time you run the function:
var dontHandle = false;
$("#home").scroll(function () {
if (dontHandle) return; // Debounce this function.
dontHandle = true;
window.setTimeout(function() {
dontHandle = false;
}, 400); // Debounce!--don't let this function run again for 400 milliseconds.
});
Here's your updated JSFiddle. You may need to play with the debounce time. Best of luck.
I'd say your code is working as intended but I have a couple thoughts about the scroll event.
The scroll event will only be fired if scrolling actually takes place. Nothing will happen if your div doesn't scroll. You could get around that by using another library, check out this stackoverflow answer for some suggested libraries. Also, keep in mind that the scroll event is extremely sensitive, so the "skipping" of images may simply be a result of scrolling too fast.
I cleaned up your code to make better use of the change_background function.
var numberofscroll = 0;
var lastScrollTop = 0;
$(document).ready(function(){
$("#home").scroll(function(e) {
var st = $(this).scrollTop();
console.log(numberofscroll, lastScrollTop, st);
(st > lastScrollTop) ? numberofscroll++ : numberofscroll--;
//make sure numberofscroll stays in range
if(numberofscroll <= 0) {
numberofscroll = 1;
} else if(numberofscroll > 4) {
numberofscroll = 4;
}
change_background(numberofscroll);
lastScrollTop = st;
});
function change_background(numberofscroll) {
$("#home").css("background-image","url('http://coverjunction.s3.amazonaws.com/manual/low/colorful" + numberofscroll + ".jpg')");
}
});
Your change_background functions have been rolled into one function and numberofscroll will stay within a certain range to ensure the image you want actually exists.
Hope that helps!

When Using Critical CSS, Jquery function does is not running on load

I'm trying to optimise my website (http://www.mazion.co.uk).
As such, I tried to create critical CSS for the site using penthouse. (See Critical CSS used here - this was generated by the main developer of penthouse for me).
However, when using critical CSS, one of the subpages on my website does not load properly. BUT, when I fully inline the CSS (or don't do anything to optimise CSS), this sub-page loads correctly.
On this sub-page - http://www.mazion.co.uk/courses, there are a number of boxes that are resized using a JS function (see below) that is run on.ready and on.resize (i.e. when resizing the screen) which ensures that all boxes are of the same size.
When using critical CSS, the resizing function works on.resize but not on.ready. On the other hand, with inline CSS, the resizing function works as expected on.resize and on on.ready...
Thus, I was wondering if someone could help me in identifying the problem. I have tried to inline the styles for the boxes directly into the HTML, but I was unsuccessful...
You can see this problem by going to http://www.mazion.co.uk/courses/ and having a look at the boxes. If you then resize your browser, all the boxes will resize themselves so that they are all the same height... This resizing that make all the boxes the same height should actually happen automatically when the page loads....
Js Function (Not Extremely important to question, but helps in setting the scene)
jQuery(document).ready(function($){
$(window).resize(function() {
resizeCourseBoxes()
resizeTopBespokeCoursesBoxes()
resizeMidBespokeCoursesBoxes()
}).resize(); // Trigger resize handlers.
});
// Ensure that all the courses boxes are the same height (this ensures that the rows are of the same size...)
function resizeCourseBoxes() {
jQuery(function($) {
courseHeader = $('.course_header')
maxTextHeight = Math.max.apply(
Math, courseHeader.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < courseHeader.length; i++) {
currentHeight = courseHeader[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight + 10
courseHeader[i].style.marginBottom = new_padding + 'px'
};
})
}
// Ensure that all mid section (prices section) of the bespoke section is the same
function resizeTopBespokeCoursesBoxes() {
jQuery(function($) {
CoursePriceSection = $('.green_bx_top')
maxTextHeight = Math.max.apply(
Math, CoursePriceSection.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < CoursePriceSection.length; i++) {
currentHeight = CoursePriceSection[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight + 10
CoursePriceSection[i].style.marginBottom = new_padding + 'px'
};
})
}
// Ensure that all mid section (prices section) of the bespoke section is the same
function resizeMidBespokeCoursesBoxes() {
jQuery(function($) {
CoursePriceSection = $('.green_bx_mid')
maxTextHeight = Math.max.apply(
Math, CoursePriceSection.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < CoursePriceSection.length; i++) {
currentHeight = CoursePriceSection[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight
CoursePriceSection[i].style.marginBottom = new_padding + 'px'
};
})
}
The answer to my problem was simple:
Critical CSS is specific for each HTML page. Thus critical CSS for each individual page should be calculated separately...
(I was using the same critical CSS for all my subpages...).

Changing a dom element's position after load without jquery

hey i have some code that sets an elements style.width, height, and position
but its not working and I assumed it was because it was'nt in the head, but I want to change the css on like a mouseclick event so tabs will slide out and stuff but I'd rather not use jquery is there a way to do this?
edit: ok so Iv got the width and height problem solved exact it doesnt seem to respond when I try and position it
here's my code
for (i=1; i<=tab_array.length-1; i++)
{
if (i==3)
{
document.getElementById("_"+i).style.cssText='height:'+Math.floor(p(100,gheight))+'px;'+
'width:' +Math.floor(p(80,gwidth ))+'px;'+
'background:black;'+
'postion:absolute;'+
'left:'+Math.floor(p(tab_array.across,gwidth)-gwidth)+'px;'
;
}
else
{
document.getElementById("_"+i).style.cssText='height:'+Math.floor(p(80,gheight))+'px;'+
'width:' +Math.floor(p(80,gwidth ))+'px;';
}
}
Try something like:
function E(e){
return document.getElementById(e);
}
function changeSize(id, height, width, interval){
var es = E(id).style, h = parseInt(height), w = parseInt(width), f = Math.floor(h/w), n = parseInt(interval), i = 0;
var sit = setInterval(function(){
i++; es.cssText = 'height:'+i*f+'px; width:'+i+'px;';
if(i === w){
es.cssText = 'height:'+h+'px; width:'+w+'px;'; clearInterval(sit);
}
}, n);
}
changeSize('box', 100, 50, 20);
For the working example, visit http://jsfiddle.net/PHPglue/X6TMv/ . I did not add easing, which jQuery handles quite effectively though. I made the code to take Strings or Numbers from height on.

DOM manipulation slow in Chrome (hiding / showing elements)

I've put together a small test at http://jsfiddle.net/Hwqb3/3/ this morning. This is on the back of a larger project with pagination. I have tried this with native JS and jQuery. The test uses jQuery.
A quick search on SO says that Chrome handles things poorly if background-size is set, but this is not the case here. No trace of background-size in the source, and inspecting elements shows no background-size being set / inherited.
Ignore the initial page load while 5,000 elements are added to the list. It is only a few seconds, but it just so there are some elements to test with.
In Firefox 18.0.1, the moving between pages is almost instant and in IE9 there is maybe a 0.1s delay between mouse click and the paged results refreshing; However, in Chrome (24.0.1312.57 m) the delay is a noticeable 1-2 seconds.
I spent the majority of my night last night pouring over my code to see if I can find the cause before writing this test. This is bare bones and still has the issue.
I can only assume that Chrome is handling the element.style.display=''; poorly. Without that (even looping through the 5,000 elements to display='none') the thing is snappy.
Any ideas? Client wants pagination on a result set of around 4,000 - 7,500, but doesn't want page reloads and doesn't understand that they should apply filters to whittle that list down to <100, as no one is ever going to page through 200 - 375 pages looking for something specific.
Last resort is AJAX calls, which may be slightly quicker on Chrome. Untested yet though.
Thanks in advance.
Code from jsfiddle, excluding the jQuery CDN link
HTML:
First
Previous
Next
Last
<br>
<ul id='list'>
</ul>
JS:
window.onload=function() {
window.list=$('#list'), window.max=20, window.page=0, window.pages=0, window.elements;
var i=0;
while(i<5000) {
i++;
list.append("<li>"+i+"</li>");
}
jump('first');
};
function jump(operation) {
window.elements=list.find('li');
window.pages=Math.ceil(window.elements.length/window.max);
if(operation=='first') {
window.page=0;
}
else if(operation=='last') {
window.page=(window.pages-1);
}
else if(operation=='+1') {
window.page=(window.page+1);
if(window.page>=window.pages) {
window.page=(window.pages-1);
}
}
else if(operation=='-1') {
window.page=(window.page-1);
if(window.page<0) {
window.page=0;
}
}
var showing=0, total=0;
window.elements.each(function() {
var show=false, self=$(this);
if(showing<window.max) {
if(total>=(window.page*window.max) && total<((window.page*window.max)+window.max)) {
self[0].style.display='';
showing++;
show=true;
}
}
if(!show) {
self[0].style.display='none';
}
total++;
});
}
check this
window.onload = function() {
window.list = $('#list'),
window.max = 20,
window.page = 0,
window.pages = 0,
window.elements;
var i = 0;
var html = '';
while(i < 5000) {
i++
html += '<li>' + i + '</li>';
}
list.append(html);
window.elements = list.find('li');
window.pages = Math.ceil(window.elements.length/window.max);
jump('first');
};
function jump(operation) {
if (operation == 'first')
window.page = 0;
else if (operation == 'last')
window.page = window.pages - 1;
else if (operation == '+1')
(window.page + 1 >= window.pages) ? window.page = window.pages - 1 : window.page++ ;
else if (operation == '-1')
(window.page - 1 < 0) ? window.page = 0 : window.page--;
var index = page * window.max;
window.elements.hide().slice(index, index + window.max).show();
}
http://jsfiddle.net/Hwqb3/16/

How to improve image cross-fade performance?

I want to be able to do a cross fade transition on large images whose width is set to 100% of the screen. I have a working example of what I want to accomplish. However, when I test it out on various browsers and various computers I don't get a buttery-smooth transition everywhere.
See demo on jsFiddle: http://jsfiddle.net/vrD2C/
See on Amazon S3: http://imagefader.s3.amazonaws.com/index.htm
I want to know how to improve the performance. Here's the function that actually does the image swap:
function swapImage(oldImg, newImg) {
newImg.css({
"display": "block",
"z-index": 2,
"opacity": 0
})
.removeClass("shadow")
.animate({ "opacity": 1 }, 500, function () {
if (oldImg) {
oldImg.hide();
}
newImg.addClass("shadow").css("z-index", 1);
});
}
Is using jQuery animate() to change the opacity a bad way to go?
You might want to look into CSS3 Transitions, as the browser might be able to optimize that better than Javascript directly setting the attributes in a loop. This seems to be a pretty good start for it:
http://robertnyman.com/2010/04/27/using-css3-transitions-to-create-rich-effects/
I'm not sure if this will help optimize your performance as I am currently using IE9 on an amped up machine and even if I put the browser into IE7 or 8 document mode, the JavaScript doesn't falter with your current code. However, you might consider making the following optimizations to the code.
Unclutter the contents of the main photo stage by placing all your photos in a hidden container you could give an id of "queue" or something similar, making the DOM do the work of storing and ordering the images you are not currently displaying for you. This will also leave the browser only working with two visible images at any given time, giving it less to consider as far as stacking context, positioning, and so on.
Rewrite the code to use an event trigger and bind the fade-in handling to the event, calling the first image in the queue's event once the current transition is complete. I find this method is more well-behaved for cycling animation than some timeout-managed scripts. An example of how to do this follows:
// Bind a custom event to each image called "transition"
$("#queue img").bind("transition", function() {
$(this)
// Hide the image
.hide()
// Move it to the visible stage
.appendTo("#photos")
// Delay the upcoming animation by the desired value
.delay(2500)
// Slowly fade the image in
.fadeIn("slow", function() {
// Animation callback
$(this)
// Add a shadow class to this image
.addClass("shadow")
// Select the replaced image
.siblings("img")
// Remove its shadow class
.removeClass("shadow")
// Move it to the back of the image queue container
.appendTo("#queue");
// Trigger the transition event on the next image in the queue
$("#queue img:first").trigger("transition");
});
}).first().addClass("shadow").trigger("transition"); // Fire the initial event
Try this working demo in your problem browsers and let me know if the performance is still poor.
I had the same problem too. I just preloaded my images and the transitions became smooth again.
The point is that IE is not W3C compliant, but +1 with ctcherry as using css is the most efficient way for smooth transitions.
Then there are the javascript coded solutions, either using js straight (but need some efforts are needed to comply with W3C Vs browsers), or using libs like JQuery or Mootools.
Here is a good javascript coded example (See demo online) compliant to your needs :
var Fondu = function(classe_img){
this.classe_img = classe_img;
this.courant = 0;
this.coeff = 100;
this.collection = this.getImages();
this.collection[0].style.zIndex = 100;
this.total = this.collection.length - 1;
this.encours = false;
}
Fondu.prototype.getImages = function(){
var tmp = [];
if(document.getElementsByClassName){
tmp = document.getElementsByClassName(this.classe_img);
}
else{
var i=0;
while(document.getElementsByTagName('*')[i]){
if(document.getElementsByTagName('*')[i].className.indexOf(this.classe_img) > -1){
tmp.push(document.getElementsByTagName('*')[i]);
}
i++;
}
}
var j=tmp.length;
while(j--){
if(tmp[j].filters){
tmp[j].style.width = tmp[j].style.width || tmp[j].offsetWidth+'px';
tmp[j].style.filter = 'alpha(opacity=100)';
tmp[j].opaque = tmp[j].filters[0];
this.coeff = 1;
}
else{
tmp[j].opaque = tmp[j].style;
}
}
return tmp;
}
Fondu.prototype.change = function(sens){
if(this.encours){
return false;
}
var prevObj = this.collection[this.courant];
this.encours = true;
if(sens){
this.courant++;
if(this.courant>this.total){
this.courant = 0;
}
}
else{
this.courant--;
if(this.courant<0){
this.courant = this.total;
}
}
var nextObj = this.collection[this.courant];
nextObj.style.zIndex = 50;
var tmpOp = 100;
var that = this;
var timer = setInterval(function(){
if(tmpOp<0){
clearInterval(timer);
timer = null;
prevObj.opaque.opacity = 0;
nextObj.style.zIndex = 100;
prevObj.style.zIndex = 0;
prevObj.opaque.opacity = 100 / that.coeff;
that.encours = false;
}
else{
prevObj.opaque.opacity = tmpOp / that.coeff;
tmpOp -= 5;
}
}, 25);
}

Categories