I am attempting to dynamically build a Materialize carousel (NOT a slider) from Flickr pictures, but I haven't been able to get the pictures to change. The picture that shows is always the last picture taken from Flickr, so I feel like something is scrolling, but it just isn't continuing to rotate the way a carousel should.
I've looked on SO and Google for answers, but 99% of the info is Bootstrap specific. I've added an active class to the first item and tried initializing the carousel both from inside the html as well as from the javascript, but neither seemed to help. Here is the html code:
<div class="carousel initialized" id="flickrPic"></div>
and the JS:
$.ajax({
type: "GET",
url: flickrApiUrl + $.param(flickrApiParams),
success: function(response) {
var flickrPetPics = response.photos.photo
for(i=0; i<flickrPetPics.length; i++) {
var newSlide = makeFlickrCarousel(flickrPetPics[i]);
$('.carousel-item').first().addClass('active');
$('#flickrPic').carousel();
$("#flickrPic").append(newSlide);
}
}
});
function makeFlickrCarousel(photoInfo) {
var flickPicUrl = "https://farm" + photoInfo.farm +".staticflickr.com/";
flickPicUrl += photoInfo.server + "/" + photoInfo.id + "_" + photoInfo.secret;
flickPicUrl += "_q.jpg";
//Build carousel pieces
var newItem = $("<a>").addClass("carousel-item");
var flickrImg = $("<img>").attr("src", flickPicUrl);
newItem.append(flickrImg);
return newItem;
}
Thanks for the help!
You should remove the .initialized class from the carousel div container and move the $('#flickrPic').carousel() initialization after the for loop like this:
...
for(i=0; i<flickrPetPics.length; i++) {
var newSlide = makeFlickrCarousel(flickrPetPics[i]);
$('.carousel-item').first().addClass('active');
$("#flickrPic").append(newSlide);
}
$('#flickrPic').carousel(); // <-- Initialize the carousel after the loop has created the carousel markup
...
Related
So, I'm building myself a webpage which will need to contain multiple carousels. I've been successful in creating the first carousel, but haven't been able to crack creating any others.
I've been following Christian Heilmann's Javascript carousel guide and all was going well until I tried to place 2 carousels on the same page.
As the js is affecting classes I assumed that the existing js would affect the copies too. Here's how the working carousel looks and here is how the broken carousel looks.
Any advice about the best way to go about this would be great, I'd love to keep it in vanilla js if possible. Thanks for your help!
And here's the updated js:
carousel = function(id) {
var box = document.querySelector(id + ' .project-pictures');
var next = box.querySelector(id + ' .next');
var prev = box.querySelector(id + ' .prev');
var items = box.querySelectorAll(id + ' .content li');
var counter = 0;
var amount = items.length;
var current = items[0];
box.classList.add('active');
function navigate(direction) {
current.classList.remove('current');
counter = counter + direction;
if (direction === -1 &&
counter < 0) {
counter = amount - 1;
}
if (direction === 1 &&
!items[counter]) {
counter = 0;
}
current = items[counter];
current.classList.add('current');
}
next.addEventListener('click', function(ev) {
navigate(1);
});
prev.addEventListener('click', function(ev) {
navigate(-1);
});
navigate(0);
}();
carouselA = carousel('#carousel-a');
carouselB = carousel('#carousel-b');
note: The div being affected is .project-pictures.
Thanks for your response! Im still not getting the carousel to work - it appears the same in the not working screenshot above, I feel I'm missing something pretty basic here, here's the html for reference and I've updated the js above to reflect your advice:
<div id="carousel-a">
<div class="project-pictures">
<ol class="content">
<li><img src="images/portfolio_img/design_museum/cropped/1.png">
</li>
</ol>
<div class="buttons">
<button class="prev">
</button>
<button class="next">
<span class="offscreen">Next</span> ▶
</button>
</div>
</div></div>
You are on the right track saying that the javascript affecting css class which applied to both carousels.
What you need to do is to differentiate between the two carousels. One way to do it is to create a unique id for each carousel.
For example
carousel = function(id) {
var box = document.querySelector(id + ' .project-pictures');
var next = box.querySelector(id + ' .next');
var prev = box.querySelector(id + ' .prev');
var items = box.querySelectorAll(id + ' .content li');
// ...
};
carouselA = carousel('#carousel-a');
carouselB = carousel('#carousel-b');
And in your HTML code, insert the appropriate ID for the two carousel elements.
I am using Jssor image slider in my application. the requirement is when the user clicks an image with index number 5, the user is navigated to any other page. When the user goes back to the slider page, same image should be displayed (i.e image with index number 5)instead of image with index number 1.
I am using query string to get the index number of the clicked image.
var sbIndex = '<%= Request.QueryString["SubIndex"]%>';
$('#jssor_2').$GoTo = sbIndex;
Can anyone give me a solution to get the index number of image which is clicked.
I don't know jssor, I just took a look at it. Anyway, it looks like jssor should not conflict with my answer.
You can put the index in the url, so when the client reloads, you read that index and set it. The way to do this, is putting a # in the url. Anything that is changed at the right hand side of the # will not cause a page reload, so this is a nice place to put variables meant for javascript.
Let me show a simple example of the principle. It's a photo gallery, the photos are Brussels sprouts.
<div id="buttons"></div>
<img id="image" src="">
<script>
// these are images of Brussels Sprouts
var images = [
'https://d2t35vvdhj0e6p.cloudfront.net/m/i/brussels_sprouts.jpg',
'http://www.polskafoods.com/sites/all/sites/default/files/images/brussels-sprouts-polish-recipe.jpg',
'http://www.onlyfoods.net/wp-content/uploads/2013/05/Brussels-Sprouts.jpg',
'http://www.qvm.com.au/wp-content/uploads/2013/04/Brussel-Sprouts.jpg',
'https://www.smartkitchen.com/assets/images/resources/large/1281295928Brussels%20Sprouts.jpg'
];
function generateButton(index) {
return '<input type="button" value="' + index + '" onclick="goto(' + index + ')" />';
}
function goto(index) {
if(images[index]) {
// set the url
location = '#' + index;
// set the image source
document.getElementById('image').src = images[index];
}
}
window.onload = function() {
var index = 0;
// check if any index is in the url
if(Number(location.hash.substr(1))) {
index = Number(location.hash.substr(1));
}
var buttons = '';
for(var i in images) {
buttons += generateButton(i);
}
document.getElementById('buttons').innerHTML = buttons;
goto(index);
}
</script>
I have a div that contains a number of Instagram images, produced by the instafeed.js plugin. After running the plugin, the resultant HTML looks like this:
<div id="instafeed">
<a><img /></a>
<a><img /></a>
<a><img /></a>
etc...
</div>
I am trying to find a way to load the contents of this div into an array; I believe that the easiest way would be to just take the tags, which is fine.
I'm pretty inexperienced with both JS and jQuery, which is why I'm having difficulty achieving this and I've not been able to find any forum posts that quite do what I'm hoping to achieve.
So far, all I'm trying to do is load the contents of the div into an array and print it back out to the document, which should (in my mind anyway) add the tags back into the HTML. I'm trying with both JavaScript and jQuery and having little success with either. I'd appreciate any thoughts:
JS:
var containerDiv = document.getElementById('instafeed');
var pics = containerDiv.getElementsByTagName('img');
console.log(pics); //Tells me at least that I have an array of img
for (var i = 0; i < pics.length; i++) {
document.write(pics[i]);
} //Seemingly does nothing
jQuery:
(I'm really sorry if this code is just all wrong, I really don't know jQuery very well at all)
$(document).ready(function() {
var pics = [];
$('#instafeed').find('img').each(function() {
pics.push($(this));
});
for (i = 0; i < pics.length; i++) {
console.log(pics[i]);
}
});
Any thoughts, tips or pointers would be much appreciated.
Edit:
Just to add a little background to my problem, to avoid causing any more confusion.
I'm trying to pull four random images from a user-specific Instagram feed for display on a website. instafeed.js can pull just four images and it can randomise the images, but Instagram itself always sends the four most recent images, so the plugin is just randomising the order of the same four pictures each time.
I'm trying to let the plugin send through every picture, which will go into the div instafeed. From here I want to load all of the contained images into an array so that I can randomly pick four images for display on the site.
JQuery code that you write is correct. Only you need the div where you need to put the images.
$(document).ready(function() {
var pics = [];
$('#instafeed').find('img').each(function() {
pics.push($(this));
});
for (i = 0; i < pics.length; i++) {
$('div#yourDiv').append(pics[i]);
}
});
See the line of the for()
You can extract only the SRC of the images and then make like you want
$('#instafeed').find('img').each(function() {
pics.push($(this).attr('src'));
});
console.log(pics); // returns an array of src.
Thank you to everyone who has tried to help me along with this. It turns out that the problem I was having stemmed from my query attempting to run before instafeed.js had been able to pull the images through from Instagram, and so there was nothing for it to find in the div. I've managed to fix this with a setTimeout.
For anyone who is interested, and just in case anyone else might come across this in future with a similar problem, here is my complete code (it's a little inelegant I'm sure, but I'm still a relative novice at JS.)
function snagImages() {
var pics = [];
$('div#instafeed').find('img').each(function() {
pics.push($(this).attr('src'));
});
reduceGallery(4, pics);
}
function reduceGallery(limit, pics) {
if (limit === undefined) {
limit = 4;
}
var gallery = [];
while (gallery.length < limit) {
var j = Math.floor(Math.random() * pics.length);
if ( gallery.indexOf(pics[j]) > -1) {
continue;
}
gallery.push(pics[j]);
}
displayPics(gallery);
}
function displayPics(gallery) {
for (var i = 0; i < gallery.length; i++) {
document.getElementById('gallery').innerHTML += '' + '<img src="' + gallery[i] + '" alt="Gallery Image" />' + '';
}
}
var userFeed = new Instafeed( {
options
});
userFeed.run();
setTimeout(function() { snagImages() }, 500);
I have a javascript that basically loads an array of names, and then it loads each one of those images from another website.
They're of course flickering like **.
I would like to preload these images, but since they change every 3 seconds, it's really hard to preload them.
However, only some of the images change.
You can see how it happens on this link when pressing the Factions "player count".
The current code i have is this:
$.ajax({
type: "GET",
url: "updater/updateFactions.php"
}).done(function(data) {
var newData = data.split(":");
document.getElementById('factions').innerHTML = newData[0]+"/"+newData[1];
var playerData = newData[2].split(",");
var data = "";
for(i in playerData) {
data += "<img src='http://signaturecraft.us/avatars/5/face/" + playerData[i] + ".png'>";
}
document.getElementById('factionsplayers').innerHTML = data;
});
You can get the images, preload them and change the content once all images are loaded
$.ajax({
type: "GET",
url: "updater/updateFactions.php"
}).done(function (data) {
var newData = data.split(":"),
playerData = newData[2].split(","),
promises = [],
images = $.map(function(image) {
var def = $.Deferred(),
img = new Image(),
src = 'http://signaturecraft.us/avatars/5/face/' + image + '.png';
img.onload = function() {
def.resolve();
}
img.src = src;
if (img.comlete) img.onload();
promises.push(def.promise());
return $(img);
});
$.when.apply($, promises).done(function() {
$('#factionsplayers').html(images);
});
$('#factions').html(newData[0] + "/" + newData[1]);
});
You're getting flicker because you're always replacing all of the content of the 'factionsplayers' element, forcing the browser to redraw the whole thing.
I suggest creating an entire layout that can hold all 100 player icons if they're there (a table would be one way, but there's a whole school of thought that says never use tables for layout, only for tabular data). Your javascript could then add and remove images from individual cells of the layout. Assuming your layout has multiple rows (it must, given the size of the images), you can show and hide entire rows based on whether the row has anything in it.
Since the layout pieces don't change, you'd only get noticeable flicker when whole rows came and went, or if a single cell changed often. You could further reduce the individual cell flicker by having your script not move player images that are still on the server from one update to the next. This could cause gaps in your layout, of course, which you would have to decide to handle.
I am making a project that shows two opposite views in two divs side-by-side. I have everything set up so the Tweets show in their respective div, but I'd like to make them both fade in, one tweet at a time (both sides can fade in at once, I don't mind that).
My Tweets are coming from an array, and I'm currently using the following code to push updates to the div:
for(var i=0; i < tweets.length; i++)
{
$("#proTweetList").prepend("<li><img src='" + tweets[i].profile_image_url + "' />" +
tweets[i].text+"</li>");
}
and
for(var i=0; i < tweets.length; i++)
{
$("#antiTweetList").prepend("<li><img src='" + tweets[i].profile_image_url + "' />" +
tweets[i].text+"</li>");
}
I found a great example on Stackoverflow, which is as follows:
var x=0; // The corner counter
function fading() {
$("#corner"+(++x)).fadeIn(2000); // Fade in the current corner
if (x==4) { // Last image to be faded in?
clearInterval(); // Stop interval
}
}
$(document).ready(function(){
setInterval("fading()",1000); // Call function every second
});
but I am very new to JQuery and cannot figure out how to translate this code into getting LI items in TWO different divs to fade in.
-- Derek
I would do something like this:
for(var i=0; i < tweets.length; i++)
{
var $item = $("<li style='display:none;'><img src='" + tweets[i].profile_image_url + "' />" +
tweets[i].text+"</li>");
$("#proTweetList").prepend($item);
$item.fadeIn(2000);
}
Didn't test that piece of code though, but I think it will work. This will create the list item within a jQuery object($item), that way you can use functions like fade on it directly.
You could do this with a simple plugin. This way you can attach the behaviour to as many divs as you like. I've written a very simple one (untested sorry) that may help:
;(function ($) {
$.fn.loadtweets = function (options) {
var settings = $.extend(
{
fadeTime : 1000,
delay: 2000,
tweets : array()
},
options
);
return this.each(
function() {
var _this = $(this),
tweets = settings.tweets,
index = 0;
var loadTweet = function() {
if (tweets.length > index) {
_this.prepend("<li><img src='" + tweets[index].profile_image_url + "' />" +
tweets[index].text+"</li>").fadeIn(settings.fadeTime);
index++;
setTimeout(loadTweet, settings.delay);
}
}
loadTweet();
}
);
};
})(jQuery);
You would call this plugin by going (I assume you have an array of tweets for each div):
$('#proTweetList').loadtweets({'tweets': proTweetsArray});
$('#antiTweetList').loadtweets({'tweets': antiTweetsArray});