Dual Twitter feeds with jquery fadeIn and setInterval - javascript

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});

Related

Converting Jquery to Vanilla JS stuck on AJAX

I am trying to convert an older jquery script to vanilla JS.
I have been working through most of them just one by one but am having a problem with the ajax call. Can anyone look at my original file and new file and see what is missing?
I am struggling mostly with converting the initial function calls to vanilla js. If you look at the 2nd code drop there most of the 'jquery-isms' have been rewritten in vanilla js. However I am having trouble converting my $.merge and $.extend actions. Furthermore, converting the $.ajax call to a JS version.
I tried to work on it modularly task by task but still haven't gotten it completely polished.
Jquery
(function($){
$(document).ready(function() {
$.ajax({
url: "https://api.flickr.com/services/rest/?method=flickr.galleries.getPhotos&api_key=*PRIVATE*c&gallery_id=72157720949295872&per_page=10&format=json&nojsoncallback=1",
type: "GET",
success: function(data) {
console.log("api successfully called")
let path = data.photos.photo
//for each photo, I save the different individual ids into variables so that they can be easily plugged into a URL
for (let i = 0; i < path.length; i++) {
let obj = path[i];
let farm_id = data.photos.photo[i].farm
let server_id = data.photos.photo[i].server
let photo_id = data.photos.photo[i].id
let secret = data.photos.photo[i].secret
//the static address to photos on Flickr is accessed through this address: https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}.jpg
//this variable is the direct link to access photos on Flickr, minus the ".jpg" designation that will be added, according to whether we are trying to access the medium picture or the large picture
let pic_url = "https://farm" + farm_id + ".staticflickr.com/" + server_id + "/" + photo_id + "_" + secret;
//this is the variable that stores the medium jpeg URL
let pic_url_m = pic_url + "_m.jpg";
//this stores an image tag which will be populated with a medium jpeg URL
let pic_img = ('<img src=\'' + pic_url_m + '\' alt = \"pic\" />');
//this appends the var pic_img to the photo_list div as the function loops through
//$('.body').append('#frame');
$('#photo-list').append(pic_img);
//this appends the class "paginate" to each img tag that is formed, ensuring that the the divs get passed to a later function called customPaginate
// $('img').addClass("paginate")
$('#photo-list img').addClass("paginate");
}
//this passes all divs with the class "pagination" to the function customPaginate
$('.pagination').customPaginate({
itemsToPaginate: ".paginate"
});
//when img tags with the class paginate are clicked, the following function is called
$('.paginate').click(function() {
//this variable saves the "src" or URL of (this) which is any element with the class "paginate"
let src = $(this).attr('src');
//this variable takes the "src" variable, slices the last six characters, and replaces it with "_c.jpg", a large version of the image URL
let src_l = src.slice(0, -6) + "_c.jpg";
//gives the "frame img" element a new attribute, which is the large image URL
$('#frame img').attr('src', src_l);
//allows the the "frame img" element to fade into the screen
$('#frame img').fadeIn();
//allows the "overlay" element to fade onto the screen
$('#overlay').fadeIn();
//when the "overlay" element is clicked, both the "overlay" and "frame img" elements
$('#overlay').click(function() {
$(this).fadeOut();
$('#frame img').fadeOut();
//removes the "src" attribute from "frame img", allowing it to be populated by other image URLs next time an image is clicked
$('#frame img').removeAttr('src');
});
});
}
});
});
//this function generates the customPaginate function, which paginates the images 10 to a page
$.fn.customPaginate = function(options)
{
let paginationContainer = this;
let defaults = {
//sets how many items to a page
itemsPerPage : 10
};
let settings = {};
//merges defaults and options into one one variable, settings
$.extend(settings, defaults, options);
//sets how many items will be on each page
let itemsPerPage = settings.itemsPerPage;
//sets which items are going to be
let itemsToPaginate = $(settings.itemsToPaginate);
//determines how many pages to generate based on the amount of items
let numberOfItems = Math.ceil((itemsToPaginate.length / itemsPerPage));
//this ul will contain the page numbers
$("<ul></ul>").prependTo(paginationContainer);
//loops through the ul tag the same number of times as there are pages. in this case, the loop will run 4 times
for(let index = 0; index < numberOfItems; index++)
{
paginationContainer.find('ul').append('<li>'+ (index+1) + '</li>');
}
//ensures that the current page only displays the items that should be on the specific page, and hides the others
itemsToPaginate.filter(":gt(" + (itemsPerPage - 1) + ")").hide();
//locates the first li element, adds activeClass element to it
paginationContainer.find("ul li").first().addClass(settings.activeClass).end().on('click', function(){
let $this = $(this);
//gives current page the activeClass setting
$this.addClass(settings.activeClass);
//takes activeClass setting away from non-current pages
$this.siblings().removeClass(settings.activeClass);
let pageNumber = $this.text();
//this variable designates that items located on the previous page times the number of items per page should be hidden
let itemsToHide = itemsToPaginate.filter(":lt(" + ((pageNumber-1) * itemsPerPage) + ")");
//this function merges itemsToHide and itemsToPaginate that are greater than the product of the pageNumber and the itemsPerPage minus 1, ensuring that these items are hidden from view
$.merge(itemsToHide, itemsToPaginate.filter(":gt(" + ((pageNumber * itemsPerPage) - 1) + ")"));
//designates these items as items that should be shown on the current page
let itemsToShow = itemsToPaginate.not(itemsToHide);
//hides items from other pages and shows items from current page
$("html,body").animate({scrollTop:"0px"}, function(){
itemsToHide.hide();
itemsToShow.show();
});
});
}
}(jQuery));
Vanilla JS (what im still stuck on)
(function($){
document.querySelector(document).ready(function() {
$.ajax({ //need to convert this to JS
url: "https://api.flickr.com/services/rest/?method=flickr.galleries.getPhotos&api_key=*PRIVATE*c&gallery_id=72157720949295872&per_page=10&format=json&nojsoncallback=1",
type: "GET",
success: function(data) {
console.log("api successfully called")
// ....truncated
}
});
});
$.fn.customPaginate = function()
{
let paginationContainer = this;
let defaults = {
itemsPerPage : 10
};
let settings = {};
//need to convert this extend to JS
$.extend(settings, defaults, options);
let itemsPerPage = settings.itemsPerPage;
// ....truncated
let pageNumber = qS.text();
let itemsToHide = itemsToPaginate.filter(":lt(" + ((pageNumber-1) * itemsPerPage) + ")");
//need to convert this extend to JS
$.merge(itemsToHide, itemsToPaginate.filter(":gt(" + ((pageNumber * itemsPerPage) - 1) + ")"));
});
}
}(jQuery));
First, please see: https://www.w3schools.com/js/js_ajax_intro.asp
Example you might consider.
function getPages(){
const xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function() {
// Everything you want to do with the data
// this.responseText.photos.photo
}
xmlhttp.open("GET", "https://api.flickr.com/services/rest/?method=flickr.galleries.getPhotos&api_key=*PRIVATE*c&gallery_id=72157720949295872&per_page=10&format=json&nojsoncallback=1",);
xmlhttp.send();
}

Unable to alter the css 'background-image' with Jquery

I am trying to cycle through an array of pictures to make a photo-viewer on my webpage. The cycling method is working fine, but the transferring the message unto the css is not. I am wondering if there is any syntax issues within my javascript code or a concept that I am missing out on. I know that the cycling works because the alert I have is working.
var changeIt = ""
var backgroundPic = new Array(4);
backgroundPic[0] = '("images/displayPic1.jpg")';
backgroundPic[1] = '("images/displayPic2.jpg")';
backgroundPic[2] = '("images/displayPic3.jpg")';
backgroundPic[3] = '("images/displayPic4.jpg")';
backgroundPic[4] = '("images/displayPic5.jpg")';
var picCounter = 0;
var numberOfPics = 5;
var picTimer;
function setPic(){
alert("hi I want this pic: " + backgroundPic[picCounter]);
$('slider').css('background-image', url + "backgroundPic[picCounter]");
picCounter += 1;
if(picCounter >= numberOfPics){
picCounter = 0;
}
}
$(document).ready(function(){
$('.slider').css('background-image', backgroundPic[picCounter]);
picTimer = setInterval(setPic, 2000);
});
The issue is due to the incorrect syntax you're using when concatenating the CSS property value. Try this:
var backgroundPic = [ 'images/displayPic1.jpg', 'images/displayPic2.jpg', 'images/displayPic3.jpg', 'images/displayPic4.jpg', 'images/displayPic5.jpg' ];
var picCounter = 0;
var picTimer;
function setPic() {
// note the . in the jquery object below to indicate a class selector
$('.slider').css('background-image', 'url("' + backgroundPic[picCounter % backgroundPic.length] + '")');
picCounter++;
}
$(document).ready(function() {
picTimer = setInterval(setPic, 2000);
setPic();
});
You have to set background image like this:
$('.slider').css('background-image', "url('" + backgroundPic[picCounter] + "')");
You inverted the positioning of the quotemarks on the second line of setPic.
Try: $('slider').css('background-image', 'url' + backgroundPic[picCounter]);
On your setPic function, this line
$('slider').css('background-image', url + "backgroundPic[picCounter]");
isn't missing a dot on $('.slider')?
You'll need to include double quotes (") before and after the imageUrl like this:
$('slider').css('background-image', 'url("' + backgroundPic[picCounter] + '")');
This way, if the image has spaces it will still be set as a property.

Can't figure out why my JS doesn't work

I've been messing around with JavaScript samples and ever since I edited this one I can't figure out why it wont work. Everything looks fine to me, but here is the code (JSFiddle)
https://jsfiddle.net/en2a8c1v/1/
function click(e) {
document.body.style.backgroundColor='" + e.target.id + "';
}
document.addEventListener('DOMContentLoaded', function () {
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', click);
}
});
First, make sure that in the JS settings you have no-wrap enabled (I used no-wrap head) in the load type dropdown.
Next, you need to understand that when you call e.target.id, this is already a string variable. You are literally making the background color "e.target.id". That isn't a color.
Simply change document.body.style.backgroundColor='" + e.target.id + "';
to document.body.style.backgroundColor= e.target.id;
I'm not going to touch on the fact that this is a terrible way to go about this as I am assuming you are just playing with event handling.
Maybe someone will find this usefull. Use CSS attribute: background-color:rgb(x,y,z);
You can do it on simple way, for example:
document.getElementById("elementID").style.backgroundColor = 'rgb('+ this.red + ', ' + this.green + ', ' + this.blue + ')';
These r,g,b values can be, for example:
this.red = 0;
this.green = 255;
this.blue = 130;

AJAX returns previous value in array

I'm making a website to host artwork. The idea is that when the page loads I have JavaScript run a php file that makes a query to the server to get the names and IDs of the image files (artwork.jpg) and display them as thumbnails on a page.
When you scroll over the thumbnail, the artwork is displayed larger on a different part of the screen and the description, specs, etc for the piece of art fades in. My issue is that when I make this second AJAX call it appends the value of the previously moused over image to the screen and does nothing until you've moused over at least two images.
Here's my code for the first ajax call that appends thumbnails to the page and creates a form with the value of the thumnbnail's id:
function getArtDescriptions()
{
$.post('../../path/to/script/get_art.php', function(json)
{
if (json.art.length > 0)
{
$.each(json.art,function()
{
var info =
'<div class = "thumbnail_box">'
+ '<img src = "images/thumbnails/'
+ this['img']
+ '"id = "'
+ this['ID']
+ '"> '
+ '<form id = "art_descriptions'
+ this['ID']
+ '" '
+ 'name = "art_descriptions'
+ this['ID']
+ '">'
+ '<input type = "hidden" id = "descriptions" name = "descriptions" value = "'
+ this['ID']
+ '"></form>'
+ '</div>';
});
}
}, 'json');
}
And this is the code I'm using to make the second AJAX call that is giving me a problem:
setTimeout(function get_id()
{
var tooltipTimeout;
$(".thumbnail_box img").on("mouseenter", function()
{
tooltipTimeout = setTimeout(details(this.id),0);
console.log(this.id);
});
$(".thumbnail_box img").on("mouseleave", function()
{
hideTooltip();
});
function hideTooltip()
{
clearTimeout(tooltipTimeout);
$(".description").fadeOut().remove();
}
}, 800);
//GRAB DESCRIPTIONS FROM DATABASE AND
function details(art)
{
var formname = "#art_descriptions"+art;
var filename = '../../file/path/to/script/get_descriptions.php';
//console.log($(formname).serialize());
$(".thumbnail_box img").on("mouseenter", function()
{
$.post(filename, $(formname).serialize(), function(json)
{
if (json.descriptions.length > 0)
{
//MAKE SURE TO EMPTY OUT DIV CLASSES FOR EACH TAB
$(".description").empty();
$.each(json.descriptions,function()
{
console.log("art method"+this['ID']);
$(".description").append(this['description']+this['ID']).hide().fadeIn("fast");
});
}
}, 'json');
});
};
When I console.log(this['ID']) in the get_id() method the correct value is displayed in the console, but when I console.log("art method"+this['ID'] in the details method I get a value equal to the previously scrolled over thumbnail's ID. I'd really appreciate any insight on this issue.
Is it something to do with the use of setTimeout()? My code would not run without specifying a timeout for the method. For example if I load the page and then scroll over images with ID's 14 and then 13, my console will display:
14
13
art method 14
The issue is that you are appending more of the same events. After the first mouseenter event occurs the details function is called, which then appends another mouseenter event. So subsequent calls will be doing the same thing. You can see an example of this here: http://jsfiddle.net/6qre72fk/.
var counter = 0;
$('#container1').on('mouseenter', function(){
$('#container2').text('First mouseenter');
appendingAnotherMouseEnter();
});
function appendingAnotherMouseEnter(){
$('#container1').on('mouseenter', function(){
$('#container2').text(counter);
counter++;
});
}
You can see how the counter is incremented several times due to all appended the mouseenter events.

making sure my loop is completely finished before running a function?

I have created a loop that templates my data and then appends it into a selected div, I want to make sure that this data has been completely templated and injected before I run my next function so what I really need is something like a callback function. Can anyone advise how I might do this?
JS
// Template slideshow
for (var i = 0, len = data.films.length; i < len; i++) {
var dataPath = data.films[i];
var tmp = '<li><img src="http://dummyimage.com/300/000/' + dataPath.id + '" /><h2>' + dataPath.title + '</h2></li>';
$('.slides').append(tmp);
}
// Want to run this once Im sure all data has been templated and injected
$('.flexslider').flexslider({
animation: "slide"
});​
You don't need a callback. The code that you have created is always injected by the time the loop completes.
// Template slideshow
for (var i = 0, len = data.films.length; i < len; i++) {
var dataPath = data.films[i];
var tmp = '<li><img src="http://dummyimage.com/300/000/' + dataPath.id + '" /><h2>' + dataPath.title + '</h2></li>';
$('.slides').append(tmp);
// Want to run this once Im sure all data has been templated and injected
if (i==len) {
$('.flexslider').flexslider({
animation: "slide"
});​
}
}

Categories

Resources