Hi,
I have two jquery scripts running, masonry and grayscale (http://webdesignerwall.com/demo/html5-grayscale/). When infinite scrolling (masonry) adds a new photos to the page, the new photos aren’t in grayscale..
Anyone have tried fixing this before? below are my infinite scroll code from jquery masonry..
here’s my snippet
var $j = jQuery.noConflict();
var $container = $j('.blist');
$container.infinitescroll({
navSelector : '#nav-below', // selector for the paged navigation
nextSelector : '#nav-below .nav-previous a', // selector for the NEXT link (to page 2)
itemSelector : '.blist .post', // selector for all items you'll retrieve
loading: {
img: "http://i.imgur.com/6RMhx.gif",
msgText: "Loading the next set of posts...",
finishedMsg: "All posts loaded"
}
},
// trigger Masonry as a callback
function( newElements ) {
var $newElems = $j( newElements ).css({ opacity: 0 });
$newElems.imagesLoaded(function(){
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
});
});
// kill scroll binding
$j(window).unbind('.infscr');
$j(".nav-previous a").click(function(){
$j('.blist').infinitescroll('retrieve');
return false;
});
// remove the paginator when we're done.
$j(document).ajaxError(function(e,xhr,opt){
if (xhr.status == 404) $j('.nav-previous a').remove();
});
Grayscale
var $j = jQuery.noConflict();
// On window load. This waits until images have loaded which is essential
$j(window).load(function(){
// Fade in images so there isn't a color "pop" document load and then on window load
$j(".item a img").fadeIn(500);
// clone image
$j('.item a img').each(function(){
var el = $j(this);
el.css({"position":"absolute"}).wrap("<div class="img_wrapper" style="display: inline-block">").clone().addClass('img_grayscale').css({"position":"absolute","z-index":"998","opacity":"0"}).insertBefore(el).queue(function(){
var el = $j(this);
el.parent().css({"width":this.width,"height":this.height});
el.dequeue();
});
this.src = grayscale(this.src);
});
// Fade image
$j('.item a img').mouseover(function(){
$j(this).parent().find('img:first').stop().animate({opacity:1}, 1000);
})
$j('.img_grayscale').mouseout(function(){
$j(this).stop().animate({opacity:0}, 1000);
});
});
// Grayscale w canvas method
function grayscale(src){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var imgObj = new Image();
imgObj.src = src;
canvas.width = imgObj.width;
canvas.height = imgObj.height;
ctx.drawImage(imgObj, 0, 0);
var imgPixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
return canvas.toDataURL();
}
thanks for the help..</div>“Infinite scroll” is loading new items via ajax and this stops any other javascript script to work properly.
Try to include Grayscale plugin initialization(inline script) inside of ”.blist”, where your items are, at end. Try this and tell us if is working.
I’m not sure if this works but, I would like to see a better solution by somebody else which works.
Smartik said
“Infinite scroll” is loading new items via ajax and this stops any other javascript script to work properly.Try to include Grayscale plugin initialization(inline script) inside of ”.blist”, where your items are, at end. Try this and tell us if is working.
I’m not sure if this works but, I would like to see a better solution by somebody else which works.
it’s not working also..
mabuc said
it’s not working also..
Anyway this was an idea. Ajax is capricious and very hard to work with it.
Post you question on http://stackoverflow.com/ . Maybe there somebody know the solution.
The greyscale plugin will only be run on load, and won’t be re-run when the new items are loaded.
Your best but would be to put your greyscale code into a function, that you run on load, and also when new items are loaded.
Hope that helps!
- Ed
Oh, I’ve got a solution, I had a look before but didnt really think much before I had to get back to work.
When the new elements are loaded you need to re-apply your jQuery to them. At the moment your jQuery fires when the document is loaded (i’m guessing) so when your new items are injected into the DOM there’s no callback to re-apply your jquery, this is what you need to do.
Call your greyscale in here;
function( newElements ) {
var $newElems = $j( newElements ).css({ opacity: 0 });
$newElems.imagesLoaded(function(){
$newElems.animate({ opacity: 1 }); //here's probably the best place to call greyscale function
$container.masonry( 'appended', $newElems, true );
});
});
so try $newElem.GrayScaleFunction(); in the area I marked.
As Smartik said, AJAX is a bit problematic!
Tom
SwiftIdeas said
The greyscale plugin will only be run on load, and won’t be re-run when the new items are loaded.Your best but would be to put your greyscale code into a function, that you run on load, and also when new items are loaded.
Hope that helps!
- Ed
Beat me to it 
I got it working but here’s the result when I click load more..
http://i.imgur.com/7dGy2.jpgnew snippet
var $j = jQuery.noConflict();
var $container = $j('.blist');
$container.infinitescroll({
navSelector : '#nav-below', // selector for the paged navigation
nextSelector : '#nav-below .nav-previous a', // selector for the NEXT link (to page 2)
itemSelector : '.blist .post', // selector for all items you'll retrieve
loading: {
img: "http://i.imgur.com/6RMhx.gif",
msgText: "Loading the next set of posts...",
finishedMsg: "All posts loaded"
}
},
// trigger Masonry as a callback
function( newElements ) {
var $newElems = $j( newElements ).css({ opacity: 0 });
$newElems.imagesLoaded(function(){
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
gray();
});
});
function gray() {
$j(".item a img").fadeIn(500);
// clone image
$j('.item a img').each(function(){
var el = $j(this);
el.css({"position":"absolute"}).wrap("<div class="img_wrapper" style="display: inline-block">").clone().addClass('img_grayscale').css({"position":"absolute","z-index":"998","opacity":"0"}).insertBefore(el).queue(function(){
var el = $j(this);
el.parent().css({"width":this.width,"height":this.height});
el.dequeue();
});
this.src = grayscale(this.src);
});
// Fade image
$j('.item a img').mouseover(function(){
$j(this).parent().find('img:first').stop().animate({opacity:1}, 1000);
})
$j('.img_grayscale').mouseout(function(){
$j(this).stop().animate({opacity:0}, 1000);
});
}
// kill scroll binding
$j(window).unbind('.infscr');
jQuery(".nav-previous a").click(function(){
jQuery('.blist').infinitescroll('retrieve');
return false;
});
// remove the paginator when we're done.
$j(document).ajaxError(function(e,xhr,opt){
if (xhr.status == 404) $j('.nav-previous a').remove();
});
</div>function gray(); is currently targetting all the elements, you only want to run it against var $newElems otherwise you risk the conflict of running the function twice on the same elements.
I tried your suggestion above but no luck..
$newElem.GrayScaleFunction();
I’m not sure what to put here..
