Combining jQuery Isotope and Lazy Load - javascript

Have started a project using jQuery Isotope. Initially integrated with Infinite scroll, but thought it was a little clunky.
Was hoping to replace Infinite Scroll with Lazy Load, and wondered if anyone has had any luck combining the two. Any tips to get them to play nice would be great.
Thanks a mill

If you want to use isotope's sorting/filtering functions, you will need to set the failure_limit of lazyload and trigger the event with isotope's onLayout callback.
jQuery(document).ready(function($) {
var $win = $(window),
$con = $('#container'),
$imgs = $("img.lazy");
$con.isotope({
onLayout: function() {
$win.trigger("scroll");
}
});
$imgs.lazyload({
failure_limit: Math.max($imgs.length - 1, 0)
});
});
Explanation
According to the docs ( http://www.appelsiini.net/projects/lazyload )
After scrolling page Lazy Load loops though unloaded images. In loop it checks if image has become visible. By default loop is stopped when first image below the fold (not visible) is found. This is based on following assumption. Order of images on page is same as order of images in HTML code. With some layouts assumption this might be wrong.
With an isotope sorted/filtered list, the page order is certainly different from the HTML so we need to adjust our failure_limit.
As you can see we store the jQuery object so that we can use its length-1 as our failure_limit. If you're curious as to why it is length-1, it's because of the following check in lazyload's update method.
if (++counter > settings.failure_limit) {
return false;
}
Lazy load on other events
If you are not triggering your lazyloads on scroll, you will need to swap the "scroll" trigger for whichever event you are using.
Demo
http://jsfiddle.net/arthurc/ZnEhn/

I think you might have some luck using this instead : https://github.com/fasterize/lazyload
It's library independent so won't break.

Here's working code using both jquery isotope and lazyload together successfully (tested in Chrome)
http://jsfiddle.net/wN6tC/62/
In the browser console you will get console.log('loaded image') confirmation when an image is loaded, as you scroll down. Drag the jsfiddle html box to change the width and you will see the layout change dynamically.
I added the background red class so you can see how isotope alters the dom after it loads. Most of the problems while trying to set this up come from, IMHO, isotope's dom manipulation.
I hope this is enough to get you started. Have fun.
Update:
I never tested example in other browsers, and apparently IE or FF failed to work because of the HTTPS references for the javascript resources (for some odd security reason). Replacing them was all that was needed to get it working in IE and FF as seen here:
http://jsbin.com/ajoded/
and
http://jsfiddle.net/wN6tC/73/

Related

Javascript Performance Huge page

I have an Single Page App with lots of buttons (3000 with click event) and bootstrap accordions with nested accordion. The page can be almost 1Mb of size.
My problem is that sometimes after a while, the browser becomes unresponsive and crashes. I wondered if there is something I could do to reduce the chances of this occuring or should I change the whole design?
EDIT:
For example, I'm using :
$(".plus").click(function () {
add1($(this).closest("tr"));
});
Should I use :
$(document.body).on("click", ".plus", add1($(this).closest("tr")));
Instead?
Thanks
I used the idea of delegating the click event to the parent and it seems to have improved greatly considering the number of buttons. But the main problem seems to be my design.
Thanks to Sabithpocker.
I'll also try the options of attach/detach of dom elements that aren't visible.

How can I avoid slow layout calculation on IE 11 when calling getBoundingClientRect()?

I am having a listener for displaying tooltips on hover which calculates the position of it using the jquery $.offset function.
On IE 11 I am getting horrible performance everytime that the listener is triggered causing a delay on showing the tooltip or even the hover css class of the element.
The part where the target elements are is embed on an angular app, if I load it directly the performance is just fine like in other browsers and I can see the call to getBoundingClientRect takes small time but if I interact with other views on angular before going to this one then the performance goes bad as it is shown in the screenshot.
(I know I shouldn't use jquery inside angular but I am pretty sure the problem is not because of that since it is working the first time I load the page and in other browsers too)
How could I avoid this layout recalculation or how I could find out what is causing this issue ?

.scrollTop(0) not working for getting a div to scroll to the top

I have a feeling what ever gave me problems that I tried to find a solution in this question - Can't trigger a jquery function with scroll on a particular div - might be responsible for scroll related issues here.
Short version: Can't get this, or anything similar, to work
$("#Container3").scrollTop(0);
Nothing happens really, no error in the console, no wierd behaviour, just seems to ignore the scrollTop(0) request.
Long version: I'm sorry but posting a code snippet isn't feasible as it's a complex app-like interface but I'll try to explain the issue to the best of my abilities:
Mobile responsive website that loads different interfaces depending on screen real-estate.
Smallest interface composed of 3 parts - navigation at the top, search at the bottom and content in the middle.
Content is mostly loaded during use and not at page load.
At the push of a button that re-loads the contents of a particular div I also need to scroll that div to the top for usability purposes.
While it doesn't seem to influence my problem (removing it doesn't solve the issue) I should disclose that I'm using hammer.js to simulate touch events as it might influence the solution.
The load is done outside the viewport so animations aren't needed but I'll take them as long as they get this to work.
This is what my jquery request looks like
$(document).on("click",".NavRowButton",function(event){
$("#Container3").scrollTop(0);
var $targetButtonId=$(event.target).attr("id");
$("#Content").load("/load/login/"+$targetButtonId+".php");
$("#DisplayContentName").html("<span class='NavColSpan'>"+$targetButtonId+"</span>");
$("#Container3").find(".WindowBorder").css("top","0");
});
#Container3 has the scroll bar and is the immediate parent of #Content.
This is a function I'm still building and is the solution for the problem I had before and also what I'm using now to help debugging this one:
document.addEventListener('scroll',function(event){
if(event.target.className==='Container'){
var $currentScroll=$(event.target).scrollTop();
console.log($currentScroll);
var $targetId=$(event.target).attr("id");
console.log($targetId);
}
},true);
Thanks in advance.
Edit: I just noticed that if I put a $(event.target).scrollTop(0); at the end of the scroll distance debugging function it actually resets the scroll so it seems that as long as the div is the event.target it works while from the outside as during the click function I might not selecting it appropriately.
Edit2: I just learned I can cache event.targets into variables and with a .get() inside the click function I'm sure I'm selecting the right element so it just leaves how the scrollTop(0) method works.
They now look like this(also had to add a condition to limit load events):
global variable:
$DivTestVar="";
click:
$(document).on("click",".NavRowButton",function(event){
var $targetButtonId=event.target.id;
if($targetButtonId != $("#DisplayContentName").html()){
$($DivTestVar).scrollTop(0);
console.log($($DivTestVar).get());
$("#Content").load("/load/login/"+$targetButtonId+".php");
$("#DisplayContentName").html($targetButtonId);
$("#Container3").find(".WindowBorder").css("top","0");
};
});
scroll debugging:
document.addEventListener('scroll',function(event){
if(event.target.className==='Container'){
$DivTestVar=event.target;
var $currentScroll=$($DivTestVar).scrollTop();
console.log($currentScroll);
var $targetId=event.target.id;
console.log($targetId);
}
},true);
If I click before scrolling the console.log($($DivTestVar).get()); returns empty but if at the first scroll it starts returning the correct DOM element. The scrollTop(0) is ignored anyway.
Edit3: I just want to leave a small update. I have since given up on the method I was trying to use here for something with a similar effect but not as user friendly as what I was trying to achieve. As such I no longer care about this personally but if you're reading this and have a similar problem I have come across this issue a couple more times to a smaller effect and I now think it's related to position:fixed; elements and how scrollTop() deals with that but I don't have the time to delve into it more so good luck and godspeed.
Did you try the pure JS version ?
document.getElementById('Container').scrollTop = 0
You have two possibilities, as far as I know.
1-Scroll the whole page until it reached the top of your #Content div position with jQuery.
2-Your #Content is inside a div with scroll, which scrollTop(0) will work for that (example: http://jsfiddle.net/zkp07abu/).

Problem with qTip - Tips not showing because elements load after the script

I'm not very experienced with javascript, jQuery or it's plugins but usually I manage. Anyways, my client is building a site and one of its purposes is to pick up news articles from different sites and show the titles in unordered html lists. I don't have access to his code, the news articles load up rather slow(much after the site has loaded).
I'm using qTIP and the idea is that once you hover over a news title, it will generate a tooltip. This works fine in my dev environment, because I have dummy title's that are not generated from anywhere.
The problem is that once the client sets the site up in his test environment, the scripts that load the news titles into the lists are so slow, that the qTIP-script loads before there are any elements in the lists. Hence it's not aware of any <li>'s to pick up and generate tooltips from.
Is there a way make sure that ALL of the news articles are loaded before the tooltip-script
loads? I think that a simple delay in loading the script is not very smart because some of the titles seem to take longer to load than others, so the delay would have to be rather long.
See my update at the bottom
I've been working on this problem as well, and came up with a solution similar to that provided by #Gaby. The problem with #Gaby's solution is that it doesn't create the qTip until the mouseover event has happened. This means that you won't see the qTip the first time you mouseover, but will the second time. Also, it will recreate the qTip every time you mouseover, which isn't exactly optimal.
The solution I went with is this:
$("li").live('mouseover', function() {
var target = $(this);
if (target.data('qtip')) { return false; }
target.qtip(...);
target.trigger('mouseover');
});
Here's what it does:
Sets target to the li element
Returns if that li element already has a qtip
If no qtip on li, then applies qtip to it
Sends mouseover trigger again so that qtip is activated
I know this is a bit hacky, but it seems to work. Also note that the 2.0 version of qTip should support live() as an option. As far as I can tell, the current 2.0 development branch doesn't yet support it.
UPDATE:
Here's the proper way to do this, direct from the qtip developer himself on the forums:
$('selector').live('mouseover', function() {
$(this).qtip({
overwrite: false, // Make sure another tooltip can't overwrite this one without it being explicitly destroyed
content: 'I\'m a live qTip', // comma was missing here
show: {
ready: true // Needed to make it show on first mouseover event
}
});
})
So it first makes sure that you don't recreate new qtips every mouseover with "overwrite: false". Then it makes the qtip show on the first mouseover with "show: {ready: true}".
You should use the Live Events of the jQuery framework.
Binds a handler to an event (like click) for all current - and future - matched element. Can also bind custom events.
so for example you could do something like
$("li").live( 'mouseover', function(){
$(this).qTip(...);
});
ref: http://docs.jquery.com/Events/live
Not for nothing, but I just added the show:{ready:true} in my onmouseover event. That got it working in Chrome & FF.
Yeah I came up with something similar. I think someone posted a similar one on their forums as well. I changed the mouseover-event to mousemove so that the qtip activates on the first mouseover.
$('li').live('mousemove', function() {
if( !$(this).data('qtip') ) {
$(this).qtip(...)
I also agree that this is a very hacky solution, however I couldn't come up with a better one. Maybe checking and applying the qtip in the callback function that fills the li's would be better but I don't really have access to that code.

jQuery event handlers not firing in IE

I have a list of items on a page with a set of controls to MoveUp, MoveDown and Delete.
The controls sit at the top of list hidden by default. As you mouseover an item row, I select the controls with jquery
//doc ready function:
..
var tools = $('#tools');
$('#moveup').click(MoveUp);
$('#movedn').click(MoveDn);
$('#delete').click(Delete);
..
$('li.item').mouseover(function(){
$(this).prepend(tools);
});
This works great in Firefox .. the tools move into the current row, and the click events call the ajax functions. However, in IE6 and IE7 .. no click occurs. I tried unbinding on mouseout and rebinding on each mouseover .. to no avail.
I also looked into various reasons outside of javascript (e.g. transparent png conflicts, z-index, position:absolute) .. also no solution found.
I eventually needed to add a tools row to each item and show/hide on mouse over/out. Works just as well -- the only downer is that I have much more 'tools' markup on my page.
Does anyone know why IE ignores/drops/kills the mouse events once the objects are moved (using prepend)? And why rebinding the event afterwards also has no effect? Kept me annoyed for almost 2 hours before I gave up.
IE will lose events depending on how you are adding things to the DOM.
var ele = $("#itemtocopy");
$("#someotheritem").append( ele ); // Will not work and will lose events
$("#someotheritem").append( ele.clone(true) );
I would also recommend using .live() on the click events to simplify your code a little. Mouseover/out is not supported by live yet. http://docs.jquery.com/Events/live
I just spent the whole day troubleshooting events not triggering on items appended to the DOM, (IE7, jQuery 1.4.1) and it wasn't because I needed to use live() (though, good to know, Chad), nor was it because I needed to clone the items.
It was because I was selecting anchor tags that had a "#" in them like so:
var myitem = $('a[href=#top]');
My solution was to use the "Attribute Contains Selector" like so:
var myitem = $('a[href*=top]');
Fortunately I have enough control over everything that it won't likely break in the future. This isn't technically related to appended objects, but hopefully it saves someone some time.
i had a similar problem. trying to use .ready to load a div on the initial page load.
works well in FF , but not ie7.
i have found a hack that seems to get around this.
I have load call a callback, divLoaded().
In divLoaded i check the $('#targetdiv').innerText.length < 50 or whatever you think will indicate that it didnt load. If I detect that case, i simply call the function taht loads that div again.
Oddly enough, i also add a '.' to the innerText before i recall the ajax function. It seems taht sometimes we go through 3 or 4 loops before the ajax load finally takes.
This leads me to think that document.ready works pretty flawlessly in IE7, which seems to dispel a bit of a myth that it is unreliable. What really 'seems' to be happening is that .load is a little bit flakey and doesnt work well when the page is just loaded.
I am still a bit green w/ all the jQuery stuff, so take this w/ a grain of salt. Interested to hear anyone's take on my little hypothesis.
cheers
greg

Categories