I'm having a problem with elements added with appendTo() not being immediately available in the DOM.
First, I'm reading some data from a JSON file and then appending some html to a div. Then I'm calling a random shuffler plugin to show one of the added divs at a time.
jsonUrl = "js/performers.json";
$.getJSON(jsonUrl, function(json) {
$.each(json.performers, function(i, performer) {
var html = '<div class="performer_mini">';
html += '<img src="' + performer.thumbnail + '" alt="' + performer.name + '" /><br />';
html += performer.name + '<br /></div>';
$(html).appendTo("div#performer_spotlight");
});
});
$("#performer_spotlight").randomShuffler(".performer_mini", 3000, 3000, 9000);
The random shuffler does the following:
(function($) {
$.fn.randomShuffler = function(shuffledElements, fadeInTime, fadeOutTime, timeout) {
fadeInTime = fadeInTime || 3000;
fadeOutTime = fadeOutTime || 3000;
timeout = timeout || 9000;
$(shuffledElements).hide();
var $old_element;
var $new_element;
var old_index = 0;
var new_index = 0;
function shuffleElement() {
$old_element = $new_element;
old_index = new_index;
while ($(shuffledElements).length > 0 && old_index == new_index) { // don't display the same element twice in a row
new_index = Math.floor(Math.random()*$(shuffledElements).length);
}
$new_element = $(shuffledElements + ":eq(" + new_index + ")");
if ($old_element != undefined) {
$old_element.fadeOut(fadeOutTime, function() {
$new_element.fadeIn(fadeInTime);
});
} else {
$new_element.fadeIn(fadeInTime);
}
setTimeout(shuffleElement, timeout);
}
$(this).show();
shuffleElement();
}
})(jQuery);
The first time the shuffleElement() function is called $(shuffledElements).length equals 0, so no element is displayed. On the next call to shuffleElement(), the elements added with appendTo() are available and one is selected at random as expected. Everything works correctly after that.
Is there some way to refresh the DOM or make these elements available to jQuery immediately after I add them with appendTo()? Any other suggestions for how to accomplish this?
When exactly do you call randomShuffler? You call this function after the AJAX-request succeeds? I have always believed that the element added by appendTo available immediately after the addition.
This code works very well for me:
<script language="javascript">
var test = "<div class=\"test\">1</div>";
$(test).appendTo("div#performer_spotlight");
$("div.test").html("<b>Hello</b>");
</script>
Yes, like #MeF Convi says you need to call the plugin only after the getJSON finishes:
$.getJSON(jsonUrl, function(json) {
$.each(json.performers, function(i, performer) {
var html = '<div class="performer_mini">';
html += '<img src="' + performer.thumbnail + '" alt="' + performer.name + '" /><br />';
html += performer.name + '<br /></div>';
$(html).appendTo("div#performer_spotlight");
});
$("#performer_spotlight").randomShuffler(".performer_mini", 3000, 3000, 9000);
});
Related
I am trying to make a loop that will display some images and add an event listener to each image which, when clicked will assign the appropriate value to humanGoal. I have:
var humanGoal;
function displayPicker(round){
for(var i = 0; i <= round; i++){
document.write('<img src=img/die' + i + '.png id="' + 'picker' + i + '">');
document.getElementById('picker'+i).addEventListener("click", function () {
humanGoal = i;
document.write('you picked ' + humanGoal );
});
}
}
why does humanGoal always === round+1, instead of the variable i from the for loop?
The humanGoal variable is being overwrited with every for loop iteration and holds the round + 1 value at the end. Different words speaking - it will always display a wrong index.
Solution: apply same class to the each img element, bind a click event listener and display the actual index by passing i variable inside the Array#forEach function.
function displayPicker(round){
for (var i = 0; i <= round; i++){
document.write('<img src=img/die' + i + '.png id="' + 'picker' + i + '" class="img">');
}
var elems = document.getElementsByClassName('img');
Array.from(elems).forEach((v,i) => v.addEventListener('click', function() {
console.log(`You picked ${i}`);
}));
}
displayPicker(5);
See answer to your question is simple, when you were trying to assign human goal with value of i, the loop is already been iterated over "rounds" value that why you always getting i === round inside click function.
See the below code snippet,
<html>
<script>
var humanGoal;
function displayPicker(round){
for(var i = 0; i <= round; i++){
document.write('<img src=img/die' + i + '.png id="' + 'picker' + i + '">');
document.getElementById('picker'+i).addEventListener("click", function () {
console.log("me getting called second");
humanGoal = i;
document.body.append('you picked ' + humanGoal );
});
console.log("me getting called first");
}
}
</script>
<body onload="displayPicker(4)">
</body>
</html>
for getting the correct result you can follow the approach provided by #Kind user
I have generated multiple barcodes using this code:
function getCode() {
var multipleCodes = document.getElementById('codeArea').value;
var eachLine = multipleCodes.split('\n');
console.log("eachLine = " + eachLine);
for (var i = 0; i < eachLine.length; i++) {
console.log("Inside loop: " + eachLine[i]);
var div = document.createElement('iframe');
div.innerHTML = "";
div.setAttribute('id', 'iFrameID' + i);
document.body.appendChild(div);
document.getElementById('iFrameID' + i).src = 'barCodeGenerator/generateBarCode.php?q=' + eachLine[i];
}
and trying to print it by using this method:
function printDiv(divName) {
var strName = document.getElementById("codeArea").value;
var imageId = document.getElementsByClassName('decoded');
var imagObject = new Image();
imagObject = imageId;
var originalImage = '<img id="imageViewer" src="' + imageSrc + '" style="padding-top: 20px" alt="' + imageSrc + '" />';
popup = window.open('', 'popup', 'toolbar=no,menubar=no,width=700,height=650');
popup.document.open();
popup.document.write("<html><head></head><body onload='print()'>");
popup.document.write(originalImage);
popup.document.write("</body></html>");
window.close('popup');
popup.document.close();
setTimeout(function () { popup.close(); }, 8000);
}
which only print single image by merging all barcodes.
How can i print them separately as multiple images.
Any help will be appreciated.
The most part of this code is irrelevant to your question. Consider removing your logs, the parts about showing popup and hiding it for more clearance.
Seems imageSrc variable in your code contains the source of one image, so you need to change your code by sending the array of image sources and iterating over it:
var originalImage = '';
// assuming imageSrc is an array of image sources
for (var i=; i < imageSrc.length; i++) {
// note that I'm changing the id of the image a litle bit to ensure it will remain unique
originalImage += '<img id="imageViewer' + i + '" src="' + imageSrc[i] + '" style="padding-top: 20px" alt="' + imageSrc[i] + '" />';
}
then the rest of your code must work.
I'm looking to create an exception which creates 2 groupds based on their .php ID numbers.
I currently have a form that fills a table of images, and want to split them into groups using javascript.
currently the script looks like this:
var currentResults;
function init() {
getProducts();}
function getProducts() {
$.ajax({
url:"php/products.php",
dataType: "json",
data: { public: true },
success:function(result){
processResults(result);
}
});}
function processResults(results) {
currentResults = null;
if (!results && !results.products)
return;
currentResults = results.products;
for (var i = 0; i < results.products.length; i++) {
processResult(results.products[i]);}
$(".galleryitem").click(handleThumbnailClick);}
function processResult(result) {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">';
newDiv += '<div class="imageHover" style="background: ' + result.color + '"> </div>';
newDiv += '<img class="galleryImage" src="' + encodeImagePath(result.thumbnail) + '" />';
if (result.artist)
newDiv += '<div class="imageArtist">' + result.artist + '</div>';
newDiv += '</div>';
$('#gallery').append(newDiv);}
function handleThumbnailClick(e) {
if (!e || !e.currentTarget || !e.currentTarget.id)
return;
var id = e.currentTarget.id.substring(11);
window.location = 'product.php?id=' + id;}
function encodeImagePath(path) {
return path.replace(/#/g, '%23');}
I am looking for some simple advice on how to split this into multiple div's based on the product's ID number to do sections of 6 images at a time with different header text.
please advise!! thanks much!
Not sure if I got your idea right but something like this should solve your problem (in case you have a "parent" property in the products JSON you're getting from the server):
function processResult(result) {
if (typeof(result.parent) !== 'undefined') { // see if the element has a parent
var newDiv = 'markup goes here'; // if some of the markup would be reused you can create a new function for this
$('#galleryitem' + result.parent).append(newDiv); // just make sure the parent is already there
} else {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">'; // default behavior that you alreay had
// code skipped for brevity
$('#gallery').append(newDiv);
}
}
P.S. You should work on your code formatting -- it can be much easier to read if formatted well.
Here is my code.. When I am calling this function, iScroll() added duplicate events on LI element after change page.
function collectionOffen(asseID, imgsInFile) {
$("#thelist").empty();
// append image files into slider div..
for (var imgPageCnt = 0; imgPageCnt <= imgsInFile; imgPageCnt++) {
var html = "";
html += "<li id=" + imgPageCnt + ">";
html += "<img src='" + preThmb + "'>";
html += "</li>";
$("#thelist").append(html);
funcPreImg = function () {
previewImageBackside(asseID);
}
document.getElementById(imgPageCnt).addEventListener("click", funcPreImg);
}
$("#thelist").listview("refresh");
$.mobile.changePage("#collectionOfFiles", {
transition: "slide",
reverse: true
});
var myScroll = new iScroll('wrapper');
}
Tell me solution if any..
duplicated events are a common problem in jqm.
Try this (untestet braincode):
$(document).on('pageinit', function () {
$("#thelist").empty();
// append image files into slider div..
for (var imgPageCnt = 0; imgPageCnt <= imgsInFile; imgPageCnt++) {
var html = "";
html += "<li id='" + imgPageCnt + "' class='imgClass'>";
html += "<img src='" + preThmb + "'>";
html += "</li>";
$("#thelist").append(html);
}
//is 'asseID' defined in this context?
$(document).on('click', '.imgClass', function (e) {
if(e.handled !== true)
{
previewImageBackside(asseID);
e.handled = true;
}
});
$("#thelist").listview("refresh");
$.mobile.changePage("#collectionOfFiles", {
transition: "slide",
reverse: true
});
var myScroll = new iScroll('wrapper');
});
this should add your list elements only on initialization of the page.
also changed your javascript function into a nicer and performant jquerycall.
you also had a typo in "<li id='" + imgPageCnt + "'>", missing quotes
I found solution. Destroy iScroll object after rendering images.
Ex:-
var myScroll = new iScroll('wrapper');
myScroll.refresh();
myScroll.destroy();
take myScroll as static variable to destroy object.
I have an array with IDs and I am loading elements with these IDs from another page.
$.each(idArr, function() {
var divline = '<div class="line" id="' + this + '">';
var url = 'allitems.php #' + this + ' div';
$('#the-list').append($(divline).load(url).hide().fadeIn());
});
It works fine but I would like the loaded elements to fade in one at a time, or at least not all att once. I cannot figure out how to use .delay with my code. Or is there maybe another way?
Thank you :)
$.each(idArr, function(i,el) {
var divline = $('<div />', {'class':'line', id: el}),
url = 'allitems.php #' + el + ' div';
$('#the-list').append(divline.load(url).hide().delay(i*1000).fadeIn());
});
A simple solution is to use setTimeout :
$.each(idArr, function(i) {
var divline = '<div class="line" id="' + this + '">';
var url = 'allitems.php #' + this + ' div';
setTimeout(function(){
$('#the-list').append($(divline).load(url).hide().fadeIn());
}, i*1000);
});
Try this way:
$(".elements").each(function(i, e) { $(e).delay(i * 400).fadeIn(400); });