JQuery behaving differently in Firefox and Chrome/Safari - javascript

I have this code which places images in columns(not my code but modified). I just added a script for infinite scroll so to retain the previous order of the images, I have them nested in a page div and so I iterate through page div and then go ahead to iterate through each image within the page. The odd thing here is that Firefox seems to place the images right but chrome and safari just mess the placement up with duplicate additions. Any one got any ideas why?
var colCount = 0;
var colWidth = 225;
var margin = 10;
var spaceLeft = 0;
var windowWidth = 0;
var blocks = [];
$(function(){
$(window).resize(setupBlocks);
});
function setupBlocks() {
windowWidth = $("#container").outerWidth();
blocks = [];
// Calculate the margin so the blocks are evenly spaced within the window
colCount = Math.floor(windowWidth /(colWidth + margin*2));
spaceLeft = (windowWidth - ((colWidth*colCount)+(margin*(colCount-1)))) / 2;
for(var i=0;i<colCount;i++){
blocks.push(margin);
}
positionBlocks();
}
function positionBlocks() {
$('.page').each(function(i){
$(this).children('.block').each(function(j){
var min = Array.min(blocks);
var index = $.inArray(min, blocks);
var leftPos = (index * (colWidth + margin));
$(this).css({
'left':(leftPos + spaceLeft) + 'px',
'top':min+'px'
});
blocks[index] = min+$(this).outerHeight() + margin;
});
});
}
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
//$('div#loadmoreajaxloader').show();
$.ajax({
url: "/more",
success: function(html){
if(html){
$("#container").append(html);
setupBlocks()
//$('div#loadmoreajaxloader').hide();
}else{
$('div#loadmoreajaxloader').html('<center>No more posts to show.</center>');
}
}
});
}
});

Related

Using Json to load all images from server, and displaying them Masonry

What I'm trying to do is get 20 or so images from a folder on the server and display them using masonry.desandro and once scrolled to the bottom it will load another set of 20 images. Just like pinterest.
Currently it does load the images 20 at a time, the only problem I'm having is the first 20 display Masonry but when the next 20 load they aren't displaying Masonry
HTML
<div class="grid">
</div>
Json
$(document).ready(function() {
// The max number of images to be loaded at a time.
var limit = 16;
// JSON data will be assigned to this
var images = "";
// to remember where in JSON we are
// initialize to the value of limit - so that we can load in images
// before page scroll.
var currentIndex = limit;
// When there are fewer than `limit` images left, this
// value will be the difference between the current index
// and the length of the images array.
var stop = limit;
var grid = $(".grid");
// Make a GET request to the api
$.getJSON("***********************/newsite/api.php", function(data) {
// save the data to be used later.
images = data.weddingCakes;
console.log(data);
})
// create the first round of images.
.done(function() {
var html = "";
for (var i = 0; i < limit; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
grid.append(html)
.masonry({
gutter: 3,
itemSelector: '.grid-item',
animate: true
});
console.log("masonry")
})
.error(function() {
console.log("error");
});
$(document).scroll(function() {
// get the scoll position with support for IE
// see http://jsbin.com/egegu3/6/edit?html,js,output
// for original code.
var totalHeight, currentScroll, visibleHeight;
if (document.documentElement.scrollTop) {
currentScroll = document.documentElement.scrollTop;
} else {
currentScroll = document.body.scrollTop;
}
totalHeight = document.body.offsetHeight;
visibleHeight = document.documentElement.clientHeight;
// only load more images if the scroll bar is at the bottom
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
var diff = images.length - currentIndex;
// if the difference is > 0 then there are more images in the array
if (diff > 0) {
stop = diff > limit ? limit : diff;
getImages(currentIndex, stop);
currentIndex += stop;
}
// otherwise, reset the index before calling getImages()
else {
currentIndex = 0;
stop = diff > limit ? limit : diff;
getImages(currentIndex, stop);
currentIndex += stop;
}
}
});
});
// gets the path for each image from index to stop
function getImages(index, stop) {
var html = "";
// create the img tags.
for (var i = index; i < index + stop; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
var str = $(html);
grid.append(html).masonry("appended", str);
}
});
My JSfiddle
you were almost correct just missed a small part while reading documentation, here while appending elements you need to append HTML elements and pass same to the masonry function.
You were adding string to append and later on you were passing element to the masonry, Also this code -> var str = $(html); returns Array of HTML elements rather than string, so you need to add these elements to the grid and pass it to masonry
so your little change would be...
// gets the path for each image from index to stop
function getImages(index, stop) {
var html = "";
// create the img tags.
for (var i = index; i < index + stop; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
var str = $(html);
grid.append(str).masonry("appended", str); // This line is a change
}
I have dummy fiddle for this as well

Same Height Elements but responsive variation

I found another question on this page about having two elements with the same height even if one of them doesn't have enough elements to cover the entire area. It works really fine but after reaching a max width of 600px I would like to disable this code, like getting back to height: auto; I'm trying to solve this but without any result. Any suggestion? here's actual javascript code.
HTML
<div id="section3a" data-same-height="blocks-resize">
</div>
<div id="section3b" data-same-height="blocks-resize">
</div>
JAVASCRIPT
$(document).ready(function() {
var equalize = function () {
var disableOnMaxWidth = 0; // 767 for bootstrap
var grouped = {};
var elements = $('*[data-same-height]');
elements.each(function () {
var el = $(this);
var id = el.attr('data-same-height');
if (!grouped[id]) {
grouped[id] = [];
}
grouped[id].push(el);
});
$.each(grouped, function (key) {
var elements = $('*[data-same-height="' + key + '"]');
elements.css('height', '');
var winWidth = $(window).width();
if (winWidth <= disableOnMaxWidth) {
return;
}
var maxHeight = 0;
elements.each(function () {
var eleq = $(this);
maxHeight = Math.max(eleq.height(), maxHeight);
});
elements.css('height', maxHeight + "px");
});
};
var timeout = null;
$(window).resize(function () {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(equalize, 250);
});
equalize();
});
Thanks to everyone!

Slide dynamically added content with jQuery

I'm trying to create a simple content slider that could handle dynamically added content to the slider. None of the "lightweight" plugins I found provided such functionality or, if it did, it didn't work correctly.
var $left = $('.left'),
$right = $('.right'),
$months = $('.sub ul');
$left.click(function(){
for(i = 0; i < 3; i++){
$months.find('li').first().before($.parseHTML('<li>xxx</li>'));
}
pos = $months.position();
$months.css('left', pos.left + 90);
});
$right.click(function(){
for(i = 0; i < 3; i++){
$months.find('li').last().after($.parseHTML('<li>xxx</li>'));
}
pos = $months.position();
$months.css('left', pos.left - 90);
});
This is the code I've got so far and here's a fiddle with an example - http://jsfiddle.net/kkr4zg0r/2/. It kind of works, but the problem is that since new content is added the navigation goes off (you can see what I mean by clicking left-right a couple of times).
I understand what's the problem for this - the newly added items "shift" the content and I need to do better calculations than substracting/adding 90px to the left position of the element but I can't figure out how to get the correct index of the elements and basically get this sliding by exactly (and correctly) by 3(or 6) elements at the time.
Currently the code is adding extra elements whenever a navigation button is pressed, if I could get the index of the currently visible first/last element, I could probably tell whether I need to add more elements and only add them then.
This is a basic illustration of what I'm trying to achieve
edit
I've changed the jsfiddle to the correct one.
The whole idea is to check when adding elements is necessary and when shift is enough:
Fiddle
$(document).ready(function()
{
var $main = $('.main'),
$left = $('.left'),
$right = $('.right'),
$months = $('.sub ul');
var addCount = 3;
var liWidth = 30;
var shiftX = addCount * liWidth;
$left.click(function()
{
var currentLeft = parseInt($months.css('left'));
var totalLength = $months.find('li').length * liWidth;
if (-currentLeft + $main.width() >= totalLength)
{
for (var i = 0; i < addCount; i++)
{
$months.find('li:last').after('<li>xxx</li>');
}
}
$months.css('left', currentLeft -= shiftX);
});
$right.click(function()
{
var currentLeft = parseInt($months.css('left'));
if (currentLeft < 0)
{
$months.css('left', currentLeft += shiftX);
}
else
{
for (var i = 0; i < addCount; i++)
{
$months.find('li:first').before('<li>xxx</li>');
}
}
});
});

How would I write a variable to call all margins on all elements on the page with Jquery?

Title pretty much says it all, I duno if this is basic or advanced but I need a variable that will be the sum of all top and bottom margins of every element on the page that has margins. I don't need the left or right ones. Can this be done easily?
Try this:
function sumMargins() {
var total = 0;
$("*").each(function() {
var top = parseInt($(this).css("marginTop"));
var bottom = parseInt($(this).css("marginBottom"));
total += (top + bottom);
});
return total;
}
See this fiddle.
var x = 0;
$('*').each(function() {
x += parseInt($(this).css('margin-top'));
x += parseInt($(this).css('margin-bottom'));
});
alert(x);
Here is a working fiddle:
http://jsfiddle.net/jonigiuro/qQ6sB/
function allMargins() {
var total = 0;
$('.container *').each(function(i) {
var currentTop = parseInt($(this).css('margin-top'));
var currentBottom = parseInt($(this).css('margin-bottom'));
total = total + currentTop + currentBottom;
});
return total;
}
alert('The total of the margins is: ' + allMargins());
I added a .container div to limit the * selector, otherwise it would also include the html and the body tags, which are not consistent about the margin (I had 8 pixels).
The solutions above are faster, but this is more solid.

Loading several images with a callback()

I am looking for a way to load several hidden thumbnails on a page (around 500), calculate their total widths, and show their container once they are all loaded.
The problem is that the container keeps showing before they all are loaded.
Here is the simplified snippet i extracted from my script:
// $('#thumbScroller') is the container, and is initially hidden.
var imgs = ['http://www.google.com/images/nav_logo95.png', 'http://cdn.sstatic.net/stackoverflow/img/sprites.png?v=4'];
for(var i = 0; i < i.length; i++){
var url = imgs[i];
$('#thumbScroller').append('<img src="' + url + '" class="thumb" />');
// all elements were appened at this point
if(i == $this.totalImages-1 ){
//variable to hold total container width
var totalContent=0;
// loop through images to calculate total width
$('#thumbScroller img').each(function (s) {
totalContent += $(this).width();
//last image, show interface elements
if(s == $('#thumbScroller img').length-1){
$('#thumbScroller').width(totalContent).fadeIn();
};
});
}
}
Any help would be appreciated!
for(var i = 0; i < imgs.length; i++){
var url = imgs[i];
$('#thumbScroller').append('<img src="' + url + '" class="thumb" />');
}
var imgCount = $('#thumbScroller img').length;
var totalContent=0;
$('#thumbScroller img').load(function() {
if (!--imgCount) {
$('#thumbScroller').width(totalContent);
$('.loader').removeClass('visible');
$('.interface').removeClass('hidden');
} else {
totalContent += $(this).width();
console.log('continue...');
}
});
Because a hidden element does not have width, you need to move the element "off page" while you are performing your calculations, then move it back when done. Note, if you can't move the container, you could add the images to a different container that is "off page" while you calculate the widths, then move them into the original container when done.
var imgs = ['http://www.google.com/images/nav_logo95.png', 'http://cdn.sstatic.net/stackoverflow/img/sprites.png?v=4'];
$('#thumbScroller').css({position: 'absolute', left: '-99999px'});
for(var i = 0; i < i.length; i++){
var url = imgs[i];
$('#thumbScroller').append('<img src="' + url + '" class="thumb" />');
// all elements were appened at this point
if(i == $this.totalImages-1 ){
//variable to hold total container width
var totalContent=0;
// loop through images to calculate total width
$('#thumbScroller img').each(function (s) {
totalContent += $(this).width();
//last image, show interface elements
if(s == $('#thumbScroller img').length-1){
$('#thumbScroller').width(totalContent);
$('.loader').removeClass('visible');
$('.interface').removeClass('hidden');
};
});
}
}
$('#thumbScroller').css({position: '', left: ''});

Categories