Loop does not work as intended - javascript

http://codepen.io/abdulahhamzic/pen/aNexYj
I'm trying to get this loop to correctly print out ten results on the screen, but it seems like there is something wrong with my loop and I can't figure out what that is. On Mozilla, I only get the first result displayed on the screen and it seems like the loop is stuck after the first iteration, and on Chrome I get the ten results, but it looks like the loop is still running afterwards since I can't really do any styling on the newly created elements, plus I still get that loading icon on the page. Can anyone help me in fixing this loop? Here's the code:
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=aa&limit=10&callback=?";
$(document).ready(function(){
$.getJSON(url, function(json){
for (var i = 0; i < json[1].length; i++){
document.write("<div><span class='header' style='color:red'>" + json[1][i] + "</span><br>" + json[2][i] + "</div><br>")
}
})
})

The document.write() function is dangerous and has different behaviour over different browsers. Better not use it. You can have something like the below working code:
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=aa&limit=10&callback=?";
$(document).ready(function(){
$.getJSON(url, function(json){
for (var i = 0; i < json[1].length; i++){
$("body").append("<div><span class='header' style='color:red'>" + json[1][i] + "</span><br>" + json[2][i] + "</div><br>")
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

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;

Endless looping when src value is changed in Internet Explorer

I have a problem with some javascript in Internet Explorer.
It works fine in other browsers.
I have the following method, that changes the src property of an images and when this happens a download of that image should start. See below:
for (var i = 0; i < imagesStartedDownloading.length; i++) {
if (imagesStartedDownloading[i] == false && responseItems[i] == true) {
console.log("image", i);
var url = baseurl + "/ImageDownload/?imageName=" + hash + "_" + imageDegrees[i] + ".jpg" + "&r=" + Math.random();
imagesStartedDownloading[i] = true;
images.eq(i).attr("src", url);
}
}
The problem is that in when changing this property Internet Explorer starts an endless loop of downloading images. Notice that i have put a console.log in the for-loop. I can confirm that this for-loop does not run in an endles loop. It is only run once for each image that should be downloaded. So that is not the problem.
The behaviour can actually be seen on this page: http://www.energy-frames.dk/Konfigurator. Hit F12 and check in the network tab. Make a change to image on the homepage so a download of new images is started, e.g. Bredde(Width in english), see below:
When this change is made new images are downloaded in an endless loop(it happens almost every time in IE). See below of what you could change
I have really spent a lot of time debugging in this and i cant see why it behaves like this in IE but not in all other browsers.
So does anyone have any idea why this happens? Or have some suggestions on what i could try?
EDIT:
#gxoptg
I have tried what you suggested. using "javascript:void 0" like this:
var newimg = $("<img class='rotator" + (isMainImage ? " active" : "") + "' src='javascript:void 0' />");
and this:
img.attr("src", "javascript:void 0");
gives me this error:
On the other hand, if i completely remove the line img.attr("src", "");
in the imgLoadError method, then i see that images are not downloaded in an endless loop. On the other hand they are not displayed. So am i using the javascript:void 0 wrong?
When i do the following:
img.attr("src", "void(0)");
Then the there is not endless loop but the image wont appear in IE - still works fine in chrome.
Here’s the reason:
for (var i = 0; i < totalnumberofimages; i++) {
var url = "";
var isMainImage = i == currentDragImg;
var newimg = $("<img class='rotator" + (isMainImage ? " active" : "") + "' src='' />");
newimg.on("error", imgLoadError);
newimg.on("load", imgLoaded);
imgcontainer.append(newimg);
}
Note the var newimg = $(...) line. In Internet Explorer, setting an empty src attribute on an image triggers the error event. Due to the error, the imgLoadError function is called. It looks like this:
function imgLoadError(e) {
var img = $(e.currentTarget);
var imgSrc = img.attr("src");
if (imgSrc.length > 0 && img.width() <= 100) {
setTimeout(function () {
var imgUrl = img.attr("src");
img.attr("src", "");
img.attr("src", imgUrl);
}, 200);
}
}
In this function, you run img.attr("src", ""), which sets the empty src attribute, triggers the error event, and calls imgLoadError function again. This causes the endless loop.
To prevent the error (and therefore the endless loop), set image source to "javascript:void 0" instead of "" in both code pieces. This source is valid and should work properly.
(According to comments, all the code is located in /Assets/Scripts/directives/image.rotation.directive.js file.)
An alternative solution is to set the src attribute to a valid, minimal, Base64 encoded image, as in http://jsfiddle.net/leonardobraga/1gefL8L5/
This would avoid triggering the endless error handling and it doesn't impact the code size that much.

Placing elements within a container div into an array - jQuery or JavaScript

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

Cannot append in IE, works in Firefox and Chrome

I think IE hates me. Everything I do in other browsers works, but IE 11, no! It is failing. I'm guessing it's me and not the browser.
I have a <select> list on my web page, and I'm trying to bind the <option> dynamically.
So far, it works great in Firefox and Chrome, but not in IE. There is no error in the IE Development tools (F12) so I'm lost as to why it refuses to work.
JSFIDDLE
HTML
<select id="MyList">
</select>
Javascript
$(function() {
var myItems=[];
myItems.push({"All":"Hello"});
myItems.push({"One":"And More"});
myItems.push({"Two":"Lots More"});
for (i = 0; i< myItems.length;i++) {
for (item in myItems[i]) {
var x = myItems[i][item]; //for my testing
var y = myItems[item]; //for my testing
$("#MyList").append("<option>" + item + "</option>");
}
}
});
If you try the fiddle in FF or Chrome, all good. The select list populates with All, One and Two.
Short of a gift or even some form of sacrifice to the IE elves, what do I need to do to make IE happy with me?
This is bizarre. When I run that fiddle in the IE I have handy (IE9), I get an "access denied" error and jQuery isn't loaded. If I change the fiddle to use 1.11.0 rather than 1.10.1, I don't get that error and the script runs.
There are a couple of issues with the code, primarily undeclared variables (your code was falling prey to The Horror of Implicit Globals); here's an updated fiddle with:
Variable declarations
Using jQuery 1.11.0
Using the "no wrap - body" option rather than "onload", since you're using the ready event
Here's the code:
$(function() {
var myItems=[];
myItems.push({"All":"Hello"});
myItems.push({"One":"And More"});
myItems.push({"Two":"Lots More"});
var i, item;
for (i = 0; i< myItems.length;i++) {
for (item in myItems[i]) {
var x = myItems[i][item];
var y = myItems[item];
$("#MyList").append("<option>" + item + "</option>");
}
}
});
Separately, though, to be compatible with a wider range of browsers, you might want to use the Option constructor and the add method of the options list rather than appending a DOM element; some older browsers prefer it. That looks like this: Fiddle
// Before the loop...
var options = $("#MyList")[0].options;
// ...in the loop
options.add(new Option(item));
JSFIDDLE
var sel = $("#MyList");
sel.empty();
for (var i = 0; i< myItems.length;i++) {
for (var item in myItems[i]) {
var x = myItems[i][item];
var y = item;
console.log(x);
console.log(y);
sel.append('<option value="' + x + '">' + y + '</option>');
}
}
As already mentioned by # T.J.Crowder in IE 10 jquery1.10.1 is not working and updating the jquery version to later it started to work;
Try this
$(function() {
var myItems=[];
myItems.push({"All":"Hello"});
myItems.push({"One":"And More"});
myItems.push({"Two":"Lots More"});
for (i = 0; i< myItems.length;i++) {
for (item in myItems[i]) {
var x = myItems[i][item];
$('#MyList')
.append($("<option></option>")
.attr("value",x)
.text(item));
}
}
});

jQuery - removing an alert stop code from working

The code below works, but there is an issue with it.
That issue is that unless the alert(this.href); - (about line 11) is in the code the following function does not work.
//There are pages which make up 2 chapters in this content
//We shall attempt to grab all the links from these pages
var c;
var chapters = new Array();
chapters[0] = "original/html/0/ID0EFJAE.html";
//Loop through each page of links
$.each(chapters, function(key, value) {
$("#theContent").append("<div class='chapterindex" + key + "'>working</div>");
$(".chapterindex" + key).load(value + " .content");
alert(this.href);
$(".chapterindex" + key + " div.link a").each(function(intIndex) {
alert(".chapterindex" + key);
});
});
If I take the first alert out of line 11 then the last alert doesn't fire. What am I doing wrong?
The delay that the alert is causing is allowing the data in your load call to load. I suspect that when you remove the alert the data does not load in time.
Try using a callback with your load call, something like (code not tested) -
$(".chapterindex" + key).load(value + " .content",function () {
$(".chapterindex" + key + " div.link a").each(function(intIndex) {
alert(".chapterindex" + key);
});
});
The first alert is probably giving the load function enough time to finish so when you take it out the load function is not done when its trying to fire your second alert.

Categories

Resources