Call jQuery when something happens - javascript

So I am using jQuery Masonry and I want to call some jQuery every time it loads posts:
function manipulate(id) {
$(id).each(function(){
if($(this).height()>200){
$('#container2').append(this);
} else{
$('#container').append(this);
};
});
};
So I want to call this function every single time that the next item in the Masonry container loads. This way it manipulates the item in the correct manner. How do I do that?
Update: description of Masonry
Masonry is a Javascript plug in that is like CSS floats forced to fit perfectly + infinite scrolling. It completely hides everything that would not be on page 1 if there was no infinite scroll, and then loads them when necessary. This means that my function will not affect any of the hidden items and needs to be recalled whenever Masonry loads the next set of items so that they appear in the right places. This could mean that without knowing Masonry, it is not necessarily possible for you to solve my problem, but you still can. A the end, Masonry "appends" the items to the Masonry container, and then "shows" them. So I guess what I need to do is append them to the correct containers after they have been appended to the Masonry container, but before it gets shown.
Masonry code:
$(window).load(function(){
var $wall = $('#container');
$wall.imagesLoaded(function(){
$wall.masonry({
itemSelector: '#entry, #entry_photo',
isAnimated : false
});
});
$wall.infinitescroll({
navSelector : '#page-nav',
nextSelector : '#page-nav a',
itemSelector : '.entry, .entry_photo',
bufferPx : 2000,
debug : false,
errorCallback: function() {
$('#infscr-loading').fadeOut('normal');
}},
function(newElements) {
var $newElems = $(newElements);
$newElems.hide();
$newElems.imagesLoaded(function(){
$wall.masonry( 'appended', $newElems,{isAnimated: false}, function(){$newElems.fadeIn('slow');} );
});
}); $('.entry').show(500);
});
I have tried putting the function in the Masonry blocks and even as the $newElems function to see if it will work when more images load, but it does not, and in fact somewhat breaks it.
How can I get it to run all the new elements loaded by Masonry through my jQuery so that they get appended to the right container?

You only declared one Masonry instance for container, container2 has no Masonry instance, so it can't infinitely scroll anything.
Also, ($(this).height()>200) will always be false if the image has not loaded yet, it'll default to undefined -> 0 > 200, which is always false. Either you need to wait for the image to load before placing it, or somehow get the dimensions of the image when the content is being loaded. You could hide it by default and place it in container, then on imagesloaded, check the height, and move it to the appropriate container and show it.

Another idea is to bind an action to jQuery's .on() ( http://api.jquery.com/on/ ). on() binds on future elements as well, assuming they are properly attached to the DOM (for example through .append() ). So for example you can bind .click() events, on elements that have not been created yet.
Finally you can do a neat trick and make .append() trigger an event. Then attach a handler for that event to the big container where things are appended, so a function is automatically called. Here is a good example of that on append() do something, and a jsfiddle http://jsfiddle.net/rzRVu/
PS. on a sidenote, I see you function takes as input an ID, but then you call .each(). Id's in html code should be unique.
Update. I missed that you tried to do it properly through masonry, what breaks exactly? I see you are calling .imagesLoaded() on a jQuery variable, is that a plugin?

So using things said on the answers provided, I messed around and discovered how it was done...so the 'appended' part in imagesLoaded just needed to be replaced with the function! It was really a simple answer...I just had to replace this:
$wall.masonry( 'appended', $newElems,{isAnimated: false},
function(){$newElems.fadeIn('slow');} );
with this:
$wall.masonry(manipulate($newElems) ,{isAnimated: false},
function(){$newElems.fadeIn('slow');} );
Problem solved!

Related

jQuery slideDown on load

I am loading a a partialView using ASP.NET MVC in my jQuery code. The partialView contains some explanation about the item that is clicked in my click function, and I would like the explanation to slide down once the object is "loaded".
I have the following code:
$('.details').click(function(){
$('#details').load($(this).data('url'), { id: $(this).data('id')}).slideDown('slow');
//the slidedown part doesn't seem to work.
});
But the .slideDown() doesn't seem to work. How can I got about this? Should I use .animate() instead?
Thanks!
EDIT
I found some questions saying I might need to .hide() it first. This seems to work, however it seems the "element" is not completely loaded when it slides down as some of the text updates after finishing the .load().
Is there some way to run the .slideDown() once the load finishes?
It's just because $().load() is not immediate. There is a third parameter that is a callback than runs when load is complete, so, you need to await to slide down (not tested, sorry).
Can you try this?
$('#details').load($(this).data('url'), { id: $(this).data('id')}, function() { $(this).slideDown('slow'); });
and tell us if it works.

finding the div height always return zero jquery

I am using jquery to find div's height, but it always returns zero. I can clearly see the height of the div in chrome's inspect element css window.
<div class="findheight">some text here</div>//original height is 21px
But when i do the following it returns zero:
$('.findheight').height() //it always returns zero. really making me sick
So I thought div might not have text when i call height method on it and i did like below.
if($('.findheight').text().length > 6){
alert($('.findheight').height());//This also returns zero so weird
}
I also tried by setting windows.timeoutcall, but that does not help with any delay time.
Can any one help me why I am always getting zero?
If the content of your divs are loaded dynamically, then you will need to use window.load event to get its correct height as discussed here: https://stackoverflow.com/a/13071846/1845408
$(window).load(function() {
alert($('.findheight').height());
});
Copied your code into jsfiddle, the height is 18
<div class="findheight">some text here</div>//original height is 21px
alert($('.findheight').height());
Did you wrap your jquery in a function that executes when the dom is ready?
$(document).ready(function(){
console.log($('.findheight').height());
});
It works for me otherwise your error may be browser specific.
Here is a jsfiddle of it working. Just check your console.
https://jsfiddle.net/lesshardtofind/vzxd4t57/
If for some reason you wouldn't have access to the element on document ready, such as working in dynamically templated frameworks like Meteor, Ember, React, or Angular then each object has a hook to register your functions in.
If otherwise you were trying to get access to an element in between transitions you could set a interval.
var interval;
var timeout = setTimeout(function(){
clearInterval(interval)
}, 10000); // destroy interval after 10 seconds to prevent memory leak
interval = setInterval(function(){
if($('.findheight').length > 0){
// execute your code here because you know this element is in the dom
clearInterval(interval);
clearTimeout(timeout);
// clear both timeout and interval
}
}, 100); // loop every 100 milliseconds to "poll" for the node in the dom
Try doing this:
$('div.findheight').height();
The .height() takes exactly CSS's height property.
If it's a dynamic content you have to handle this in the respective event..
For example:
If you're working with the content on page load like #renakre said, use $(window).load() or $(document).load() to trigger the call.
If it's a content generated from some other process you have coded, you have to bind respective event.. let's presume it's a click or on:
$(document).load(function() {
// Shows the height on page load
console.log($('.findheight').height());
$('#another-element-ID').click(function() {
// .. code which populate the div dynamicaly
// Shows the height
console.log($('.findheight').height());
});
$('.another-element-class').on('change', function() {
// .. code which populate the div dynamicaly
// Shows the height
console.log($('.findheight').height());
});
});
Hope this can help you.
This happens when an explicit height/width is not set for that element OR when the CSS for inner/outer elements set the height/width to 0;
To get height/width like this you have to explicitly set height/width.

Infinite Scroll + Swipe.js

Background:
I'm making a portfolio site utilising both Swipe.js and Infinite Ajax Scroll (JQ).
Problem:
When the content from extra pages is loaded into the current page, it is not processed by the already-loaded Swipe.js script. This means that the new content doesn't have it's mark-up changed (needed for the swipe functionality to work).
I think I need to get the Swipe.js script to fire after each page re-load. Would that fix it? Please explain this to me like I'm an 8yr old. JS is not a strong suit...
Demo:
http://hatchcreative.co.nz/tomo
You can see that as the page loads new content, the buttons on either side of the sliders no longer work.
Yes you're right, after the images are loaded you have to create a new Swipe instance on these new elements (as they weren't there at the beginning, when the page was loaded).
Based on the docs of infinite scroll you can use onRenderComplete.
So you had your jQuery.ias constructor like this:
jQuery.ias({
// ... your settings...
onRenderComplete: function(items) {
$(items).each(function(index, element) {
new Swipe(element);
});
}
});
This should work this way somehow, but I am not exactly sure; I haven't worked with these libraries yet.
Edit:
After some more inspection of your code, I saw you had some inline click handler like: onclick='two.prev();return false;'.
You need to remove this and add your onclick handle in the same onRenderComplete function.
onRenderComplete: function(items) {
var swipe;
$(items).each(function(index, element) {
swipe = new Swipe(element);
});
// find tags with the class 'forward' inside the current element and add the handler
$(element).find('.forward').on('click', function() {
swipe.next();
});
// ... also for previous
}
By the way: Usually you should provide a jsFiddle with your important code parts, so it's easier for us to get the problem, and the question is not getting obsolote when the linked page changes.

jQuery infinite-scroll Not Triggering

I'm making a simple little website to apply a different formatting style to Reddit posts, I'm trying to add the infinite-scroll jQuery plugin but it doesn't do anything. I tried following the (very simple) instructions on the infinite-scroll page and when it didn't do anything I thought I must have entered something wrongly, but then I just copy/pasted the code from the Masonry/Infinite-Scroll example and it still didn't work. Masonry is working perfectly (finally) but I just can't figure out what is wrong with infinite-scroll. I understand the basics of jQuery and JavaScript, but obviously not as much as most of you people, so could you please help me out and let me know what is wrong? My site is live at reddit.ymindustries.com.
Thanks heaps, you guys have rarely failed me so far.
YM
EDIT: If there aren't enough images to fill up the page on the homepage, visit reddit.ymindustries.com/r/aww for more images.
EDIT 2: I believe I located the issue, it is described here: https://github.com/paulirish/infinite-scroll/issues/5
Now to figure out a fix...
EDIT 3: Added a little bit of a hack in to make it sort of work, but it just seems to loop the second page endlessly now. Hmm...
I think your problem is actually css. Make your page longer that client area height. add more images to $container
Point is, botom edge of your $container need to pass bottom of window so scroll event fires so infinite scroll can react on this event and calculate weather or not edge is reached
BTW, in same cases, for instance, when I shrink my window, the example you set is working.
=== UPDATE ===
I found some time to play with infinitescroll and here is final working script, just set pathParse method in your script
$(function () {
var $container = $('#itemContainer');
$container.imagesLoaded(function () {
$container.masonry({
itemSelector:'.item'
});
});
$container.infinitescroll({
navSelector:'.navigation', // selector for the paged navigation
nextSelector:'.navigation #next', // selector for the NEXT link (to page 2)
itemSelector:'.item', // selector for all items you'll retrieve
bufferPx:40,
debug:true,
columnWidth:function (containerWidth) {
return containerWidth / 5;
},
loading:{
finishedMsg:'No more pages to load.',
img:'http://i.imgur.com/6RMhx.gif'
},
pathParse: function(path,page){
return $(this.nextSelector).attr("href");
}
},
// trigger Masonry as a callback
function (newElements) {
// hide new items while they are loading
var $newElems = $(newElements).css({ opacity:0 });
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded(function () {
// show elems now they're ready
$newElems.animate({ opacity:1 });
$container.masonry('appended', $newElems, true);
});
//console.log("test (never fired :( )");
}
);
});
Now, since your next link will not update by it self (http://reddit.ymindustries.com/?after=t3_yh4av), you need to change the callback to pull out last element from ajax response and change next link... could be something like this
function (newElements) {
// hide new items while they are loading
var $newElems = $(newElements).css({ opacity:0 });
// ensure that images load before adding to masonry layout
// ======> if query parameter after=... is caring filename then do this
var lastImageUrl= $newElements[$newElements.length-1].attr("src");
var lastFileName= lastImageUrl.substring(lastImageUrl.lastIndexOf("/") +1, lastImageUrl.lastIndexOf("."));
$("#next").attr("href", "http://reddit.ymindustries.com/?after="+lastFileName);
$newElems.imagesLoaded(function () {
// show elems now they're ready
$newElems.animate({ opacity:1 });
$container.masonry('appended', $newElems, true);
});
//console.log("test (never fired :( )");
}
You also need to take care of wich version of infinite-scroll your using since if you use the ones that comes with masonry/isotope (version 2.0b2.110713), both need a little hack in order to call the function and not use the predefined array:
//old code, to be changed (line 489)
desturl = path.join(opts.state.currPage);
// new code
desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
This is already fixed in the newer versions of infinite-scroll
I had the same problem with jQuery's "infinitescroll" and Masonry. You might just solve this by giving your page more initial items so that the plugin's scrolling detection kicks in.
In WordPress this is under the "Reading" settings. By default WordPress only opens 10 items at a time. You could increase that number to 100/page to be more sure the window will be full initially. I had some code here that was just horrible, turns out I just needed longer pages, not more code.
So it's difficult to test these plugins on large displays if you don't have enough images. Maybe the solution is to scale the images larger on large displays so you're more sure about getting your content below the fold.
If you think someone might get to your website with a really huge display, I'm not sure what the answer is other than showing more items/page and maybe adding $('#masonry').infinitescroll('retrieve'); to your footer to load an extra page just in case.

How to execute jQuery function after Ajax page load

I'm building Wordpress website where all content pages are loaded using Ajax. This is causing me a problem with jQuery localScroll plugin. This plugin will add animated scroll to all anchor links on the page. Problem is that using script below I'm able to have animation on that page only after one of the links on the page is clicked.
I think I understand why is this happening. My guess is that after I click on the main menu script will execute but since Ajax content is not yet loaded events are not attached to Ajax loaded content links. Now I'm stuck, I have no clue how to fix this. Would you mind helping me with this one?
Thank you in advance.
$(function(){
$('a').live('click', function() {
$('#portfolioWrap').localScroll({// Only the links inside that jquery object will be affected
target: '#portfolioWrap', // The element that gets scrolled
axis:'y', // Horizontal scrolling
duration:1500
});
});
});
EDIT
Just a note to others after I managed to make this work. I tried all suggestions here. My guess is that solutions suggested by o.v. and Ohgodwhy should work, but probably due to website complexity and maybe plugin limitations I wasn't able to make them work. For example .on function didn't work at all although I'm using jQuery 1.7.1. At the end I implemente ajaxComplete suggested by Just_Mad and that worked. Thank you all for your help!
This is the code:
$(function() {
$('#wrapperIn').ajaxComplete(function() {
$('#portfolioWrap').localScroll({
target: '#portfolioWrap', // The element that gets scrolled
axis:'y', // Horizontal scrolling
duration:1500
});
});
});
If you use jQuery.ajax to load AJAX content you can try to bind to ajaxComplete event, to get the moment, when any ajax is complete.
Elaborating on what GoldenNewby said, listen/attach with the .on() method introduced in jQuery 1.7.
$(function(){
$('body').on('click', 'a', function() {
$('#portfolioWrap').localScroll({
target: '#portfolioWrap', // The element that gets scrolled
axis:'y', // Horizontal scrolling
duration:1500
});
});
});
No need to use AJAX for callbacks for listening/binding to elements. The above function will place a click function on all elements found within the body{1} at/after page load. This includes all dynamically created links.
{1} - Change 'body' to whatever Container has the ajax data. I.E. #portfolioWrap
Add a callback to the ajax load, good place to start is at http://api.jquery.com/jQuery.ajax/ under "success callback"
I would have given more specific advice, but your snippet is a bit isolated, maybe if you created a jsfiddle?

Categories

Resources