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/
Related
I have a simple loading bar made with css, you update the css and the bar fills, super simple.
I decided to update the bar with jQuery, works great but now I throw it into a practical environment. I have a bunch of files being downloaded and each time a file successfully downloads, it updates the position. The main problem is that it downloads the files so fast, and places the files correctly fast enough that it just doesn't update the loading bar unless I set a timeout interval of 300-400ms..it does log into console and I made an interval function that continously checks to see if a file is finished based on a global variable. No matter where I place the function to update the loading bar or how I update it, it seems the Dom will not react unless there's a big enough delay between files OR it will react at the very end (jumps to 100).
Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?
I also tried promises too but it didn't change how the browser reacts to the function.
This is all being done inside a Cordova environment but I tested it on chrome too and it works as long as the pc is powerful enough it seems.
The file Transfer function has an "on Success" too but that doesn't do anything as the Dom wont update in it until after all the downloads are done OR there's a delay
My solutions so far is to either intentionally lag the downloader, or lag it every 10 or 20 files to update the position
Edit: here's my loading bar Js
var colorInc = 100 / 3;
function setWater(myval)
{
var val = myval;
var waitForMe = $.Deferred();
if(val != ""
&& !isNaN(val)
&& val <= 100
&& val >= 0)
{
setTimeout(function(){waitForMe.resolve()}, 100);
var valOrig = val;
val = 100 - val;
if(valOrig == 0)
{
//$("#percent-box").val(0);
$(".progress .percent").text(0 + "%");
}
else $(".progress .percent").text(valOrig + "%");
$(".progress").parent().removeClass();
$(".progress .water").css("top", val + "%");
if(valOrig < colorInc * 1)
$(".progress").parent().addClass("red");
else if(valOrig < colorInc * 2)
$(".progress").parent().addClass("orange");
else
$(".progress").parent().addClass("green");
}
else
{
setTimeout(function(){waitForMe.resolve()}, 100);
$(".progress").parent().removeClass();
$(".progress").parent().addClass("green");
$(".progress .water").css("top", 100 - 67 + "%");
$(".progress .percent").text(67 + "%");
//$("#percent-box").val("");
}
return waitForMe.promise();
};
Dowload tracker:
var DLProgress = null;
function updateProgress() {
var oldNum = 0;
DLProgress = setInterval(function(){
if(!doneArts) {
doneArts = true;
downloadHelper("Articles",articleSize,33.33,0);
}else if(currPos >= totalSize - 1){
clearInterval(DLProgress);
goNews();
currPos = 0;
doneArticles = false;
doneJson = false;
doneArts = false;
} else if(currPos >= articleSize && !doneArticles) {
doneArticles = true;
downloadHelper("json",jsonSize,33.33,33.33);
} else if(currPos >= articleSize + jsonSize && !doneJson) {
doneJson = true;
downloadHelper("img",imgSize,33.33,66.66);
}
if(oldNum != currPos) {
oldNum = currPos;
setWater(Math.ceil(100 * currPos / totalSize));
}
},5);
}
Download Helper :
function downloadHelper(name,size,maxPerc,startingPoint) {
dataFiles[name].forEach(function(file){
var getItem = localStorage.getItem(name+"/"+file[0]) || null; //might not work
if(getItem === null || getItem !== file[1]) {
//download file.
if(file[0] !== null && file[1] !== null) {
//setWater(Math.ceil(100 * currPos / totalSize)).done(function(){downloader(name+"/"+file[0],file[1]);});
setTimeout(function(){downloader(name+"/"+file[0],file[1])},window.dltime);
window.dltime += 200;
}
}
});
};
File transfer used :
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file-transfer/
It Does update after each download helper has finished
Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?
The DOM is updated each time the download is completed - it could be a problem.
We should separate upload progress and animation. When file is downloaded you should just change some kind of Model and use requestAnimationFrame recursively to animate a progress bar.
requestAnimationFrame is called 60 times per second, but will generally match the display refresh rate, paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life.
I think you have the case with the variable currPos. Use debug tool to mark the lines and inspect value of currPos. Somehow your code is managed to jump it 0 to articleSize.
$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)
}
});
Here's my code which I hosted in a public folder in dropbox
This simple animation freezes after a while when running on google chrome, I tested on 4 different browsers(Chrome, IE 9, Opera, Firefoc). The "page loading" animation runs smooth on all browsers except chrome, what might be causing this?(wont run on jsfiddle as well)
PS: It may take up to 10 - 15 secs until the animation freezes, I know this wouldn't be a problem in the application later, but I still wanna know why it does so because it doesnt on other browsers.
you call infiniteLoop with a few setTimeouts. Why don't us simply use recusion for this?
EDIT: This one works as you may want it to work. It uses jQuery's step callback to calculate the percentage. if it is > 70 %, it starts the next animation.
$(document).ready(function() {
var parent = $('.loadingBar').width(),
parentWidth = parent.toString(),
colors = ["red","blue","yellow","green"],
idx = 0;
var extend = function(color) {
var colorClass = '#' + color + 'Bar',
currentIndex = parseInt($(colorClass).css('z-index')),
afterIndex = currentIndex + 4;
var backColor = $(colorClass).css('background-color');
$(colorClass).css('z-index', afterIndex)
.animate({width:parentWidth},
{step:function(width,tween){
var percent = Math.round(width/parentWidth*100);
if((typeof $(this).data("next") === "undefined" || $(this).data("next") === null) && percent >= 70){
$(this).data("next",true);
if(idx > colors.length-2)
idx = 0;
else
idx++;
extend(colors[idx]);
}
},
duration:2000,
complete:function(){
$(this).data("next",null);
$(this).css('width', '0px');
$('.loadingBar').css('background-color', backColor);
}
});
}
extend(colors[0]);
});
I want to display several images of the same size at the same position, one at a time, with a 5s interval between each change. To do so I've used jQuery.Timer, that uses setInterval() to call some show_next_image() function every 5s.
It actually does work with IE, Opera, Safara, Firefox and.. partly with Google Chrome. It's not working with Google Chrome if I open a new window and directly type my website URL: it'll show the second image and stop. And with any other situation (reload, from another link, not right after opening a new window) it'll badly work: one can see the back image before the front image is shown.
Thus I'm wondering whether I've done something wrong with my JavaScript source. What I do is I use a front and a back image. When I want to show the next image, the back img source is set to the new image, and the front image is faded out while the back one is faded in through jQuery. You can check it out at http://www.laurent-carbon.com/ (in French). The two img are identified with bg1 and bg2.
var images = ["/img/IMG_0435bg.jpg", "/img/IMG_0400bg.jpg", "/img/maisonnette 2.jpg", "/img/IMG_0383bg.jpg", "/img/IMG_0409bg.jpg", "/img/IMG_0384bg.jpg"];
var idx = 1;
var waitTime = 5000; // ms
$(document).ready(function() {
$("#bg2").hide();
$.timer(waitTime, load_next);
$.preLoadImages(images);
});
function load_next(timer) {
var toshow = images[idx];
idx++;
idx %= images.length;
back_image().attr('src', toshow);
swap_images();
}
function front_image() {
return (idx % 2 == 0) ? $("#bg1") : $("#bg2");
}
function back_image() {
return (idx % 2 == 0) ? $("#bg2") : $("#bg1");
}
function swap_images() {
back_image().fadeOut('slow');
front_image().fadeIn('slow');
}
Thanks,
Ceylo
Ok I've worked out a solution .... without the use of plugins.
Demo
http://jsfiddle.net/morrison/PvPXM/9/show
source
http://jsfiddle.net/morrison/PvPXM/9/
This approach is a lot cleaner and removes the problem I had while viewing your page in chrome: the animation getting out of sync and flashing.
The only thing you have to do in the HTML is wrap the two images in a <div id="fadeBox" style="position:relative"></div>
$(function() {
var images = [
"http://www.laurent-carbon.com/img/IMG_0435bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0400bg.jpg",
"http://www.laurent-carbon.com/img/maisonnette 2.jpg",
"http://www.laurent-carbon.com/img/IMG_0383bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0409bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0384bg.jpg"
];
var idx = 1;
var max = images.length;
var easing = "swing";
var waitTime = 5000; // ms
var fadeTime = 2000; // ms
var fadeShow = function(fadeTime, fadeDelay) {
var $topImage = $("#fadeBox img:last");
$topImage.fadeTo(fadeDelay, 1, function() {
$topImage.fadeTo(fadeTime, 0, easing, function() {
$topImage
.fadeTo(0, 1)
.insertBefore("#fadeBox img:first")
.attr("src", images[++idx == max ? idx = 0 : idx]);
fadeShow(fadeTime, fadeDelay);
});
});
};
fadeShow(fadeTime, waitTime);
});
Hope this helps
PS thanks to Levi for cleaning the code up a bit.
Answer: http://jsfiddle.net/morrison/RxyZY/
Notes:
You are trying to reinvent the wheel. You are creating a simple slideshow. There are numerous plugins to do exactly this and much more. I used jQuery cycle in my example, which is extremely customizable.
You should wrap your stuff up in a function, creating an expression. In my example, the (function($){}(jQuery)) is what does the trick. It scopes your variables to the function, rather than the global namespace.
Here's the code I'm trying to understand:
noniefix.js:
function fixNonIE() {
if(YAHOO.env.ua.ie > 0) {
return false;
}
var divs = YAHOO.util.Dom.get('bd').getElementsByTagName('div');
if(divs.length > 0) {
YAHOO.util.Dom.batch(divs, pushup);
alert (divs.length+" divs in file!");
}
}
function pushup(el) {
if(el.id.search('fixer') != -1) {
return;
}
if(el.innerHTML.search('javascript:textWindow') != -1) {
el.style.zIndex = parseInt(el.style.zIndex) + 1;
}
var pushupTags = Array('p');
if(pushupTags.length > 0) {
for(var t=0; t<pushupTags.length; t++) {
var elems = el.getElementsByTagName(pushupTags[t]);
YAHOO.util.Dom.batch(elems, (function(e) { e.style.marginTop=0; e.style.marginBottom=0; })); //what's happening HERE?
}
}
return;
}
I've read up a bit on YUI, so I know that the batch function just takes an array of elements and applies the function to each element. What I don't understand is where the marginTop, marginBottom changes are applied. I think they are applied to each <p> tag, but I've viewed the source code of the page and can't find where this code is being inserted.
Any ideas would be greatly appreciated!
You can't see result of this function at the source code because it appplys dynamicly by JS to the each DOM tag written in array. But you can see the changes using some debugger software, builded in Internet Explorer 8 for example, or firebug under Mozilla Firefox.