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.
Related
So I'm fiddling with a fun idea for an offline website I'm currently trying to develop.
It'll be offline as it's meant to be practice for later study assignments and such.
My problem is the following: I have a javascript function that replaces a PNG with a GIF and after the animation it should redirect the person to another html I've made.
The source for the JS animation is mainly acquired from here already, but I cannot seem to make it work in the ways I originally intended.
The way it currently works is that I click the png and it'll turn into a gif (no problem there) but what I want is that it runs my js script and then redirect to another .html file (url).
The following is my HTML:
<object id="syringe">
<img src="img/syringe.png" height="750" alt="img/syringe.gif" class="center">
<h2>Click the syringe to inject yourself with a daily dose of puns and jokes</h2>
</object>
The following is the JS:
(function($) {
var getGif = function() {
var gif = [];
$('img').each(function() {
var data = $(this).data('alt');
gif.push(data);
});
return gif;
}
var gif = getGif();
var image = [];
$.each(gif, function(index) {
image[index] = new Image();
image[index].src = gif[index];
});
$('#syringe').on('click', function() {
var $this = $(this),
$index = $this.index(),
$img = $this.children('img'),
$imgSrc = $img.attr('src'),
$imgAlt = $img.attr('data-alt'),
$imgExt = $imgAlt.split('.');
if($imgExt[1] === 'gif') {
$img.attr('src', $img.data('alt')).attr('data-alt', $imgSrc);
} else {
$img.attr('src', $imgAlt).attr('data-alt', $img.data('alt'));
}
$this.toggleClass('play');
});
})(jQuery);
It is to my understanding that I can add a delay and then another function to something in the js - such as the following, which is what I intend to do, however cannot accomplish.
[FUNCTION HERE],1000,
function(){
window.location.href=myredirectionuri;
});
And that is my problem.
It looks like you want to have the gif display for a second or two and then redirect, right? If $this.toggleClass('play'); is the end, then just insert this right after it:
setTimeout(() => window.location.href = myredirectionuri, 1000);
That'll wait for 1000ms and then redirect to the new page.
In the animation script, after it changes to a gif, insert
setTimeout(function() {
/* redirect code */
}, /* length of gif in milliseconds */ )
I cannot figure out what is wrong with my code and why my API/AJAX call will not show the images that I'm calling. It appears when I console.log(results) the 10 images are called but they will not show. Here is my jquery code..
//when window loads ... function will happen
window.onload = function(){
var musiciansList = [];
var inputBox = $('#submitButton')
//whatever musician the user submits will appear
$('#submitButton').on('click', function(){
var input=$('#submitButton');
var userInput=inputBox.val();
musiciansList.push(userInput);
renderButtons();
});
function renderButtons() {
var button = $('<button>');
button.text(musiciansList[musiciansList.length-1]);
button.addClass('band')
$('.container').append(button);
};
//When I click this button a function will happen
$(document).on('click', '.band', function() {
//variable queryUrl for giphy
var queryUrl = "http://api.giphy.com/v1/gifs/search?q=music&api_key=dc6zaTOxFJmzC&limit=10";
//requesting information giphy
$.ajax({
url: queryUrl,
method: 'GET'
})//recieving information from giphy
.done(function(response) {
//returns the response from the website
var results = response.data;
var imageUrl = response.data.image_original_url;
var musicians = $('<img>');
console.log(queryUrl)
//takes var musicians and adds attr src and imageUrl
musicians.attr('src', imageUrl);
musicians.attr('alt', 'musician');
$("#images").push(imageUrl)
//prepend puts the images in the beginning
$("#images").prepend(imageUrl);
$('<img>').val();
console.log(results)
console.log(imageUrl)
//empty gifs button
$('#clearButton').click(function(event){
$(musicians).remove()
});
});
});
};
So it looks like you've got a couple of errors.
First one looks like your usage of the giphy API. If you go to http://api.giphy.com/v1/gifs/search?q=music&api_key=dc6zaTOxFJmzC&limit=10 in your browser, you can see how the data is coming back. The data is returned as an array of GIF objects that each have an "images" property that has an assortment of images you can choose from. Instead of accessing the images like
var imageUrl = response.data.image_original_url;
you need to loop through the response.data array and grab an image, as in the following example
var imageUrl = response.data[i].images.fixed_height.url;
Your other issue is when appending the image element you created to the DOM. You are appending the imageUrl variable (which is just the value of the image URL), instead of the img element you created which is stored in the musicians variable (this will also have to be a part of your loop). In addition, the following:
$("#images").push(imageUrl)
//prepend puts the images in the beginning
$("#images").prepend(imageUrl);
$('<img>').val();
can all be refactored to the single line
$("#images").prepend(musicians);
Your end result should look something like:
for(var i = 0; i < response.data.length; i++){
var imageUrl = response.data[i].images.fixed_height.url;
var musicians = $('<img>');
//takes var musicians and adds attr src and imageUrl
musicians.attr('src', imageUrl);
musicians.attr('alt', 'musician');
//prepend puts the images in the beginning
$("#images").prepend(musicians);
}
What I'm trying to do is create a dynamic wall of images.
What I'm doing is this:
Call an API to get some response. Create an array of objects based on response
Based on the array, make HTML elements for each object where there's an img in it too.
When all of these HTML elements are created, attach it to the DOM, and call a final function.
This is what I have so far (truncated to get the point across):
EDIT: code has changed a bit. scroll to bottom of question for link to current code.
// based on one post, construct the html and return it
function getOneHtml(post, w) {
console.log("getting one html");
var outerDiv = $("<div>", {class: "brick"});
outerDiv.width(w);
var img = $("<img />");
img.attr("src", post.img_src);
img.on('load', function() {
console.log("img loaded");
var ratio = this.width / w;
h = this.height / ratio;
$(this).css({'height': h});
// ...
// ...
// create the element
// an alternative I'm using for now is directly append
// the created HTML onto the page, but that results
// in a kinda messy interface.
return outerDiv[0].outerHTML;
});
}
// queries an api and then calls callback after everything is done
function requestData(subreddit, callback) {
// array of objects with link to image, post title, link to reddit
posts = [];
var w = $(window).innerWidth() / 3,
html = ''; // holds all of the inner HTML for all elements
$.get("url here", function(data) {
var arr = data.data.children;
arr.forEach(function(res_post) {
console.log("looping in requestData");
// prepare a post object
// ...
// ...
html += getOneHtml(post, w); // get the HTML for this post
});
// this should happen after everything else is done
console.log("calling callback");
callback(html);
});
}
// complete the DOM
function makeWall(html) {
console.log("making wall");
// do stuff
}
Now the trace of the program in console is this:
looping in requestData
getting one html
looping in requestData
getting one html
... // bunch of times
calling callback
making wall
(20) img loaded
So now the problem is that the HTML isn't prepared until each image is loaded, and so it doesn't actually get attached to the DOM.
How can I make sure that things happen in order in which I want them to? I tried refactoring code into more of an async style but that didn't work (not my strongest point).
I also tried looking at $.Deferred but I don't understand it, and how to integrate it into my code.
Any help is appreciated.
EDIT:
I think it might help to see what I'm doing: http://karan.github.io/griddit/
When you load, I want the images to load first, and then fade in. Currently, they show up, then hide and then fade in. Here's the source: https://github.com/karan/griddit/blob/gh-pages/js/main.js.
Also, if you scroll down one or two pages, then scroll back up, some images show up behind others.
You can use .done(), as explained in the jQuery API documentation on .done() specifically explains how to use .done() with $.get().
It's as simple as:
$.get( "test.php" ).done(function() {
alert( "$.get succeeded" );
});
Concretely...
As the API documentation link provided above indicates, you can daisy chain .done() calls together.
$.get(url,handler).done(function(){console.log('calling callback')},callback);
Note, Not certain about functionality of included plugins, i.e.g., #grid layout,
css, etc. image width, height and #grid layout not addressed, save for existing pieces re-composed in attempt at flow clarity.
Piece below solely to fulfill // Do something when all dynamically created images have loaded requirement. See console at jsfiddle
Note also, piece at jsfiddle format issue. In order to test piece, drew in 2 plugins from links at original post. Tried jsfiddle's TidyUp feature, which inserted linebreaks.
Piece may need some re-formatting; though current jsfiddle does provide callback functionality, as per original post. Again, see console. Thanks for sharing.
updated
$(function() {
// the name of the last added post
var last_added = '';
// to control the flow of loading during scroll var scrollLoad = true;
var q = 'cats';
var callbacks = $.Callbacks();
// callback,
// Do something when all dynamically created images have loaded
var callback = function (cb) {
return console.log( cb||$.now() )
};
callbacks.add(callback);
function getOneHtml(post, w, count){
var img = $("<img>", {
"src" : post.img_src,
"width" : w
});
img.on('load', function(e) {
var ratio = e.target.width / w;
h = e.target.height / ratio;
$(e.target).css('height',h)
});
var link = $("<a>", {
"href" : post.permalink,
"target" : "_blank",
"html" : img
});
var outerDiv = $("<div>", {
"class" : "brick",
"style" : "width:" + w
});
$.when($(outerDiv).appendTo("#grid"),
$(link),
count)
.then(function(div, _link, _count) {
// `image` `fadeIn`; adjustable
$(_link).appendTo($(div)).hide(0).fadeIn(2000);
return _count
})
.always(function(_count){
callbacks.fireWith(window, [_count + " images appended to grid at " + $.now()])
});
};
function requestData(subreddit,callback) {
//array of objects with link to image, post title,link to reddit
posts=[];
var w = $(window).innerWidth() / 3;
html = '';
$.ajax({
type : 'get',
url : "http://api.reddit.com/r/" + subreddit + "/hot.json?&after=" + last_added,
beforeSend : function () {
$("#searchterm").addClass("loadinggif");
},
complete : function () {
$("#searchterm").removeClass("loadinggif");
},
success : function (data) {
var arr = data.data.children;
var count = null;
arr.forEach(function(res_post) {
if(!res_post.data.is_self&&(/\.(gif|jpg|jpeg|tiff|png)$/i).test(res_post.data.url)) {
// `images` count
++count;
var post = {
'title' : res_post.data.title,
'img_src': res_post.data.url,
'name' : res_post.data.name,
'permalink': 'http://reddit.com' + res_post.data.permalink
};
getOneHtml(post, w, count);
}
last_added = res_post.data.name;
});
scrollLoad = true;
// callback,
// Do something when all dynamically created images have loaded
// see `console`; adjustable
callbacks.fireWith( window, [$(".brick img").size() + " appended to grid, callback at " + $.now()]);
}});
}
// function makeWall() {}
})
jsfiddle http://jsfiddle.net/guest271314/ggsY9/
I have a background image folder that there is some picture that i want to use them for background.
how i can get their names and put them on array whit javascript?if i cant they do with javascript,how can i do that?
i want to read name of files and use javacsript and link for change background image whit css.
<script>
function nextbg(){
$('#bg').css('background-image','url(Images/bg2.jpg)');
}
</script>
This solution is created according to the fact that browser dont have access to folders/filesystem.
Javascript can not access the filesystem. This has to be done by a server script and then be feed to the javascript.
I had the simliar problem when building my game engine when I was loading all my diffrent tiles. I ended up doing it like this.
This solution do pose two a problems when implementing it.
You will have to define the amout of images in the "NrofTiles" array
The images must be named like tile1, tile2 ... tile9 so you can
increment the path to them.
The typeOfTiles[typeCounter] is just there to give me access to different folders, in my case for my tiles, grass, houses, water and so on.
for(var i = 0; i <= nrofTiles.length; i++)
{
for(var x = 0; x <= nrofTiles[i]; x++)
{
console.log
("Fetching tile "+(x + 1 )+" of " + 14);
img = new Image();
//My path
img.src = 'Images/Cart/' + typeOfTiles[typeCounter] + '/' + (x + 1) + '.png';
imgArray.push(img);
var intervalFunctionen = function () {
alert("calls back here");
};
}//end for loop!
}end outer for loop!
When everything is loaded(the tiles), you do this to change the background picture.
This is an example of a changing body background. You could make a link with an ID lets say "iamthelink".
HTML
Change BG
JAVASCRIPT
var link = document.getElementsById('iamthelink');
link.onclick= function() {
var body = document.getElementsByTagName('body')[0];
body.style.backgroundImage = 'url(http://localhost/background.png)';
}
Is anyone able to determine, how to stop the jQuery caching the image that it grabs, and displaying the same image around and around again?
Basically the image is been re-uploaded every 5 seconds, as it acts as a webcam (if you check the time stamp on the bottom right of the image, you can tell if it's been updated or not)
http://colourednoise.co.uk/scripts/index.htm
Thank you
(sorry I forgot to hit paste for the code)
$(function(){
$(document).ready(function() {
var imgs = ['http://www.ramseycommunityradio.co.uk/images/webcam.jpg', 'http://www.ramseycommunityradio.co.uk/images/webcam.jpg']
$("#webcam").attr('src', imgs[1]);
var refreshId = setInterval(function() {
$("#webcam").fadeOut("slow", function() {
var $el = $(this);
$el.attr('src', $.inArray($el.attr('src'), imgs) === 0 ? imgs[1] : imgs[0]);
$el.fadeIn("slow");
});
}, 2000);
});
You could try appending a changing query string onto the URL, this should stop caching if that is indeed your problem. I've seen this done with a time stamp here: how to generate and append a random string using jquery
So each time you generate an image you do:
var qs = (new Date).getTime();
var url = 'http://www.example.com/images/myimage.jpg?' + qs;
$(el).attr('src',url);
your code:
var imgs = ['http://www.ramseycommunityradio.co.uk/images/webcam.jpg', 'http://www.ramseycommunityradio.co.uk/images/webcam.jpg']
$("#webcam").attr('src', imgs[1]);
var refreshId = setInterval(function() {
$("#webcam").fadeOut("slow", function() {
var $el = $(this);
$el.attr('src', $.inArray($el.attr('src'), imgs) === 0 ? imgs[1] : imgs[0]);
// this condition is redundant, it will ultimately give the same result always
// because imgs[0]==imgs[1]
$el.fadeIn("slow");
});
}, 2000);
as far a JQuery is concerned you are not changing the SRC attribute (JQuery knows nothing about the content of the image). Try using two different names in the server-side like webcam0.jpg and webcam1.jpg and alternating between them.
One trick is t append a random query string URL which causes the image to reload from the server. The code could be something like:
setInterval(function() {
var img = $("#img").get(0);
img.src = img.src.replace(/\?.*/, "") + "?" + Math.random();
}, 5000);