So in my code I created a table pulling from an XML file that displayed two columns of information about plants. The goal of my program is to be able to hover over the first and print out the other information about that plant and print it in another section to the right of my table. The issue is that I am not gettign any console errors and the hover affect is not printing any information.
window.addEventListener("load", link_events);
var xhr = false;
function link_events() {
xhr = new XMLHttpRequest();
if(xhr) {
xhr.addEventListener("readystatechange", ShowFile);
xhr.open("GET", "plants.xml", true);
xhr.send();
} else {
alert("XHR not supported.");
}
}
function ShowFile() {
var i;
var title;
var cover;
var plant_table = "<table><tr><th>Common Name </th><th>Botanical Name </th></tr>";
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//here we have gotten the file correctly
//loop through it and print out cover and title
var plantlist = xhr.responseXML.getElementsByTagName("PLANT");
//booklist is an array and each element is an object sub i
//so you have to use getElementBy something in order to pull the information
for (i = 0; i < plantlist.length; i++) {
var Common = plantlist[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Botanical = plantlist[i].getElementsByTagName("BOTANICAL")[0].firstChild.textContent;
plant_table += "<tr>" +
"<td class =\"plant\">" + Common + "</td>" +
"<td>" + Botanical + "</td>" +
"</tr>";
}
plant_table += "</table>";
document.getElementById("outarea").innerHTML = plant_table;
}
var plants = document.getElementsByClassName("plant");
for (i=0; i < plants.length; i++) {
plants[i].onmouseover = HoverChoice;
}
}
function HoverChoice() {
var input = xhr.responseXML.getElementsByTagName("PLANT");
for (i = 0; i < input.length; i++) {
Common = input[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Zone = input[i].getElementsByTagName("ZONE")[0].firstChild.textContent;
var Light = input[i].getElementsByTagName("LIGHT")[0].firstChild.textContent;
var Price = input[i].getElementsByTagName("PRICE")[0].firstChild.textContent;
if (plants == this.innerHTML) {
document.getElementById("inarea").innerHTML =
"<h1>" + Common + "</h1>" + "<br />" + "<br />" +
"Zone: " + Zone + "<br />" +
"Light: " + Light + "<br />" +
"Price: " + Price;
}
}
}
}
you could try using addEventListener method instead and see whether it works?
plants.forEach(function(plant){
plant.addEventListener("onmouseover", HoverChoice);
});
or going with the original loop you made it would be
for (i=0; i < plants.length; i++)
{
plants[i].addEventListener("onmouseover", HoverChoice);
}
I'm not anything professional, a common problem I used to encounter in these kinds of event listening functions was that calling a global function sometimes fails but making the function on the spot inside the event listener would work like addEventListener("onmouseover" , function() { return 0; });
Related
i have a quiz with radio buttons ,sow i have to save the answears on my local storge ,but im stuck i don t know what else to do,im learnig sow dont hate me pls,tnx
This is my code sow far
<form id="quiz"> </form>
<script>
let object;
let httpRequest = new XMLHttpRequest();
httpRequest.open("GET", "quiz.json", true);
httpRequest.send();
httpRequest.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
object = JSON.parse(this.response);
console.log(object)
}
let json = object
let quiz = document.getElementById("quiz");
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<div >";
html += "<input type=\"radio\" id=\"q\" checked=\"checked\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\">" + questionItem.options[i] ;
html += "</div>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
function save() {
var g1 = document.querySelector('input[type="radio]');
g1 = (g1) ? g1.value : '';
localStorage.setItem("g1", g1);
}
});
You can simplify your AJAX dialog by using fetch() instead of new XMLHttpRequest();. I straightened out a few things in your code (also see the initial remarks in #brianagulo's answer) and prepared a little set of sample data to demonstrate the whole functionality of the quiz. The jsonplaceholder.typicode.com url only serves as a working json-server endpoint. The received data is actually ignored here.
In your "production version" you will need to un-comment the line:
localStorage.setItem("quiz",JSON.stringify(ans))
The checked answers where collected in an object doing
[...document.querySelectorAll('input[type=radio]:checked')].reduce((a,{name,value}) =>(a[name]=value,a), {});
This
collects all checked radio button inputs with (document.querySelectorAll('input[type=radio]:checked')),
converts the collection of DOM elements into a proper array (with [... ])and eventually
reduce()-s its elements into an object where the element names are the property names and the (input-)element values are the property values.
And also please note that you can only store strings in local storage. Therefore I converted the ans object into a JSON string before using it in the .setItem() method.
const Q = {
quiz: [{
question: "Where was the Boston tea party?",
options: ["New York", "Detroit", "Boston", "Reno"]
}, {
question: "Where would you find Venice Beach?",
options: ["Detroit", "Venice", "Paris", "Los Angeles"]
}, {
question: "Where would you find Queens?",
options: ["London", "Paris", "Stockholm", "New York"]
}, {
question: "Where is Greenwich Village?",
options: ["London", "Paris", "Stockholm", "New York"]
}, {
question: "Where would you find the Gateway Arch?",
options: ["St. Quentin", "St. Louis", "St. Anton", "San Francisco"]
}]
}, quiz = document.getElementById("quiz");
var url = "quiz.json";
// in your productive version: comment out the following line
url = "https://jsonplaceholder.typicode.com/users/7"; // functioning test URL for fetch
function save(ev) {
ev.preventDefault();
const ans=[...document.querySelectorAll('input[type=radio]:checked')].reduce((a,{name,value}) =>(a[name]=value,a), {});
// in Stackoverflow snippets you cannot use local storage, so here is console.log instead:
console.log(ans);
// in your productive version: un-comment the following line
// localStorage.setItem("quiz",JSON.stringify(ans))
}
fetch(url).then(r => r.json()).then(object => {
// remove the following line:
object = Q; // use the static quiz from defined in Q instead ...
let json = object
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<label>";
html += "<input type=\"radio\" id=\"q\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\"> " + questionItem.options[i];
html += "</label><br>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
quiz.onsubmit=save;
});
<form id="quiz"> </form>
There is a typo on your save function. You are missing a quote after radio:
var g1 = document.querySelector('input[type="radio"]');
Also, your question is confusing but if what you are trying to do is get whether the radio is checked or not you must access the checked property and save that to localStorage. And if you want to save the state for all of the buttons then you should use querySelectorAll and save them that way instead. Example below of accessing a single input's checked value:
function save() {
// you can access it directly on this line
var g1 = document.querySelector('input[type="radio]').checked;
localStorage.setItem("g1", g1);
}
For saving them all
Lastly, it seems you are not actually calling the save() function. If your intention is to have the radios checked state saved to localStorage on click you may want to add an event to the submit button. For example:
<form id="quiz"> </form>
<script>
let object;
let httpRequest = new XMLHttpRequest();
httpRequest.open("GET", "quiz.json", true);
httpRequest.send();
httpRequest.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
object = JSON.parse(this.response);
console.log(object)
}
let json = object
let quiz = document.getElementById("quiz");
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<div >";
html += "<input type=\"radio\" id=\"q\" checked=\"checked\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\">" + questionItem.options[i] ;
html += "</div>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
function save() {
// you can access it directly on this line
var g1 = document.querySelector('input[type="radio]').checked;
localStorage.setItem("g1", g1);
}
let submitButton = document.querySelector('input[type="submit"]');
submitButton.onclick = (event) => {
/* this prevents page refresh and submission to the backend which is a form default */
event.preventDefault();
// then we call the save function here
save();
};
});
If this was helpful please consider selecting as the answer
can someone show me how to send an variable to my php file out of that construct? i am new at ajax/javascript and i try to figure out my style for writing JS code. atm i like and understand that kind of version.
var ajax = new XMLHttpRequest();
var method = "POST"
var url = "data.php" //erweitern - später
var asynchronous = true
var button = document.getElementById("count")
var counter = 0;
button.onclick = function() {
counter += 2;
showMoreFood(counter)
};
ajax.open(method, url, asynchronous)
ajax.send()
ajax.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText)
var html =""
//for (var a = 0; a < data.length; a++) {
for (var a = 0; a < 2; a++) {
var firstname = data[a].name
var preis = data[a].preis
html += "<tr>"
html += "<td>" + firstname + "</td>"
html += "<td>" + preis + "</td>"
html += "</tr>"
}
document.getElementById("data").innerHTML = html
} // if
} // onready
what i tried:
var data = "variable1"
ajax.open(method, url, asynchronous, data)
in data.php
-----------
$variableA = $_POST['variable1'];
because i thought i could send the data within, but nope. thx and br
i got it. i just need to change that to
method = "GET"
url = "data.php?variable1=something"
and in the php file
$variableA = $_GET['variable1'];
and it works :) i dont think thats the right version to handle that but it works :)
I have a javascript that reads a xml Phonebook, prints a table and I'd like to make each number clickable so it would launch a Phone App.
<table class="table table-striped table-dark" id="campanie"></table>
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xmlhttp.open("GET", "campanie-full.xml", true);
xmlhttp.send();
}
function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<thead class=thead-light><tr><th><h5 class=text-dark>Nr.</h5></th><th><h5 class=text-dark>Company</h5></th><th><h5 class=text-dark>Phone 1</h5></th><th><h5 class=text-dark>Phone 2</h5></th></tr></thead>";
var x = xmlDoc.getElementsByTagName("DirectoryEntry");
for (i = 0; i <x.length; i++) {
table += "<tr><td><p>" +
[i+1] + "</p></td><td><p>" +
x[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue +
"</p></td><td><a href=tel:>" +
x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue +
"</a></td><td><a href=tel:>" +
x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue +
"</a></td></tr>";
}
document.getElementById("campanie").innerHTML = table;
}
What should I do in order to have each a href=tel: work properly?
Also, you will see that I put the "Telephone" tag twice, as the Phonebook has more than one phonenumber. As a second question, I'd like to know how to make it read correctly, as the XML file can't be edited in any way. The <Telephone> tag from XML can't be changed to <Telephone1> or <Telephone2>. This question can wait, however.
EDIT: I have added an example XML
<CiscoIPPhoneDirectory>
<DirectoryEntry>
<Name>Doctor Dolittle</Name>
<Telephone>100</Telephone>
<Telephone>+19001234567</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Tommy Stubbins</Name>
<Telephone>101</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Chee-Chee</Name>
<Telephone>102</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Prince Bumpo</Name>
<Telephone>103</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Polynesia</Name>
<Telephone>104</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Gub-Gub</Name>
<Telephone>105</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Jip</Name>
<Telephone>106</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Dab-Dab</Name>
<Telephone>107</Telephone>
</DirectoryEntry>
You'll need to check the Xml to see whether there are 1 or 2 phone numbers. (You could also make it check for none, if that could ever happen, and not add a row at all). Then you add either the 2nd phone number or an empty cell, depending on what the data says.
Change the function that creates the table contents from the Xml response, like this...
function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<thead class=thead-light>" +
"<tr><th><h5 class=text-dark>Nr.</h5></th>" +
"<th><h5 class=text-dark>Company</h5></th>" +
"<th><h5 class=text-dark>Phone 1</h5></th>" +
"<th><h5 class=text-dark>Phone 2</h5></th>" +
"</tr></thead>";
var x = xmlDoc.getElementsByTagName("DirectoryEntry");
for (i = 0; i <x.length; i++) {
var name = x[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue;
var tel1 = x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue;
var tel2 = "";
// if there are 2 phone numbers, get the value of the 2nd one
if (x[i].getElementsByTagName("Telephone").length === 2) {
// check that it's not an empty node...
if (x[i].getElementsByTagName("Telephone")[1].childNodes) {
tel2 = x[i].getElementsByTagName("Telephone")[1].childNodes[0].nodeValue;
}
}
table += "<tr><td><p>" + [i+1] + "</p></td>" +
"<td><p>" + name + "</p></td>" +
"<td><a href='tel:" + tel1 + "'>" + tel1 + "</a></td>";
// if we don't have a 2nd phone number then add an empty cell
if (tel2 === "") {
table += "<td></td>";
}
// if we do have a 2nd phone number then add it
else {
table += "<td><a href='tel:" + tel2 + "'>" + tel2 + "</a></td>";
}
table += "</tr>";
}
document.getElementById("campanie").innerHTML = table;
}
I apologize up front for the possible lack of clarity for this question, but I'm new to Angular.js and my knowledge of it is still slightly hazy. I have done the Angular.js tutorial and googled for answers, but I haven't found any.
I have multiple select/option html elements, not inside a form element, and I'm populating them using AJAX. Each form field is populated by values from a different SharePoint list. I'm wondering if there is a way to implement this using Angular.js?
I would like to consider building this using Angular because I like some of it features such as data-binding, routing, and organizing code by components. But I can't quite grasp how I could implement it in this situation while coding using the DRY principle.
Currently, I have a single AJAX.js file and I have a Javascript file that contains an array of the different endpoints I need to connect to along with specific query parameters. When my page loads, I loop through the arrays and for each element, I call the GET method and pass it the end-point details.
The code then goes on to find the corresponding select element on the page and appends the option element returned by the ajax call.
I'm new to Angular, but from what I understand, I could create a custom component for each select element. I would place the component on the page and all the select and options that are associated with that component would appear there. The examples I've seen demonstrated, associate the ajax call with the code for the component. I'm thinking that I could use a service and have each component dependent on that service and the component would pass it's specific query details to the service's ajax call.
My current code - Program flow: main -> data retrieval -> object creation | main -> form build.
Called from index.html - creates the multiple query strings that are passed to ajax calls - ajax calls are once for each query string - the very last function in the file is a call to another function to build the form elements.
var snbApp = window.snbApp || {};
snbApp.main = (function () {
var main = {};
main.loadCount = 0;
main.init = function () {
function buildSelectOptions(){
//***
//Build select options from multiple SharePoint lists
//***
var listsArray = snbApp.splistarray.getArrayOfListsForObjects();
for(var i = 0; i < listsArray.length; i++){
var listItem = listsArray[i];
var qryStrng = listItem.list +
"?$select=" + listItem.codeDigits + "," + listItem.codeDescription + "," + listItem.ItemStatus + "&$orderby=" + listItem.codeDescription + "&$filter="+listItem.ItemStatus+" eq true" + "&$inlinecount=allpages"
var listDetails = {
listName: listItem.list,
listObj: listItem,
url: "http://myEnv/_vti_bin/listdata.svc/" + listItem.list +
"?$select=" + listItem.codeDigits + "," + listItem.codeDescription + "," + listItem.ItemStatus + "&$orderby=" + listItem.codeDescription + "&$filter="+listItem.ItemStatus+" eq true" + "&$inlinecount=allpages"
};
var clientContext = new SP.ClientContext.get_current();
clientContext.executeQueryAsync(snbApp.dataretriever.letsBuild(listDetails), _onQueryFailed);
}
//***
//Build select option from other API endpoint
//***
var listDetails = {
listName:"SNB_SecondaryActivityCodes",
url: "http://myEnv/requests/odata/v1/Sites?$filter=(IsMajor eq true or IsMinor eq true) and IsActive eq true and IsPending eq false and CodePc ne null and IsSpecialPurpose eq false&$orderby=CodePc"
};
snbApp.dataretriever.letsBuild(listDetails);
}
buildSelectOptions();
//***
//Add delay to populate fields to ensure all data retrieved from AJAX calls
//***
var myObj = setTimeout(delayFieldPopulate,5000);
function delayFieldPopulate(){
var optObj = snbApp.optionsobj.getAllOptions();
var osType = $("input[name=os_platform]:checked").val();
snbApp.formmanager.buildForm(osType, optObj);
}
};
function _onQueryFailed(sender, args) {
alert('Request failed.\nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
}
return main
})();
AJAX calls here - called from main/previous file:
var snbApp = window.snbApp || {};
snbApp.dataretriever = (function () {
var listsArray = snbApp.splistarray.getArrayOfListsForObjects();
function getListData(listItem) {
var eventType = event.type;
var baseURL = listItem.url;
$.ajax({
url: baseURL,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
}
})
.done(function(results){
snbApp.objectbuilderutility.buildObjectFields(results, listItem);
})
.fail(function(xhr, status, errorThrown){
//console.log("Error:" + errorThrown + ": " + myListName);
});
}
function _onQueryFailed(sender, args) {
alert('Request failed.\nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
}
return{
letsBuild:function(item) {
getListData(item);
}
};
})();
Builds a item name object - called from recursive AJAX calls / previous file
var snbApp = window.snbApp || {};
snbApp.objectbuilderutility = (function () {
function formatItemCode(itemCode, eventType){
if(eventType !== 'change'){ //for load event
var pattern = /^CE/;
var result = pattern.test(itemCode);
if(result){
return itemCode.slice(2);
}else{
return itemCode.slice(0,3);
}
}else{ //for change event
var pattern = /^CE/;
var result = pattern.test(itemCode);
if(result){
return itemCode.slice(2);
}else{
return itemCode.slice(3);
}
}
}
return{
buildObjectFields: function(returnedObj, listItem){ //results:returnedObj, prevItem:listItem
//***
//For SharePoint list data
//***
if (listItem.listName !== "SNB_SecondaryActivityCodes") {
var theList = listItem.listName;
var firstQueryParam = listItem.listObj.codeDigits;
var secondQueryParam = listItem.listObj.codeDescription;
var returnedItems = returnedObj.d.results;
var bigStringOptions = "";
//regex to search for SecondaryFunctionCodes in list names
var pattern = /SecondaryFunctionCodes/;
var isSecFunction = pattern.test(theList);
if(isSecFunction){
bigStringOptions = "<option value='0' selected>Not Applicable</option>";
}else{
bigStringOptions = "<option value='0' disabled selected>Select Option</option>";
}
$.each(returnedItems, function (index, item) {
var first = "";
var second = "";
for (var key in item) {
if (item.hasOwnProperty(key)) {
if (key != "__metadata") {
if (key == firstQueryParam) {
first = item[key];
}
if (key == secondQueryParam) {
second = item[key];
}
}
}
}
bigStringOptions += "<option value=" + first + " data-code=" + first + ">" + second + "</option>";
});
var str = theList.toLowerCase();
snbApp.optionsobj.updateFunctionOrActivity(theList.toLowerCase(), bigStringOptions);
//***
//For other API
//***
} else {
var theList = listItem.listName;
var bigStringOptions = "<option value='0' disabled selected>Select Option</option>";
var returnedItems = returnedObj.value;
for(var i = 0; i < returnedItems.length; i++){
var item = returnedItems[i];
//***
//change event type means the user selected a field
//***
if(listItem.eventType === "change"){
var siteCodeChange = item.SiteCodePc;
if (typeof siteCodeChange === "string" & siteCodeChange != "null") {
siteCodeChange = siteCodeChange < 6 ? siteCodeChange : siteCodeChange.slice(3);
}
bigStringOptions += "<option value='" + item.Id + "' data-code='" + siteCodeChange + "' data-isDivSite='" + item.IsDivisionSite + "' data-isDistSite='" + item.IsDistrictSite + "' data-divID='" + item.DivisionSiteId + "' data-distID='" + item.DistrictSiteId + "'>(" + siteCodeChange + ") " + item.Name + "</option>";
snbApp.formmanager.buildSelectSiteLocations(bigStringOptions);
//***
//load event which means this happens when the page is loaded
//***
}else{
var siteCodeLoad = item.SiteCodePc;
if (typeof siteCodeLoad === "string" & siteCodeLoad != "null") {
var siteCodeLoad = siteCodeLoad.length < 4 ? siteCodeLoad : siteCodeLoad.slice(0, 3);
}
bigStringOptions += "<option value='" + item.Id + "' data-code='" + siteCodeLoad + "' data-isDivSite='" + item.IsDivisionSite + "' data-isDistSite='" + item.IsDistrictSite + "' data-divID='" + item.DivisionSiteId + "' data-distID='" + item.DistrictSiteId + "'>(" + siteCodeLoad + ") " + item.Name + "</option>";
snbApp.optionsobj.updateFunctionOrActivity(theList.toLowerCase(), bigStringOptions);
}
}
}
}
};
})();
Form management - called from previous file, gets all select elements on page and appends items from the object in previous file to each select element.
var snbApp = window.snbApp || {};
//Direct interface to the form on the page
snbApp.formmanager = (function(){
var form = {};
form.content_holder = document.getElementById("content_holder");
form.sec_act_codes = document.getElementById("snb_secondary_activity_codes");
form.prim_func_codes = document.getElementById("snb_primary_function_codes");
form.sec_func_codes = document.getElementById("snb_secondary_function_codes");
form.sec_func_nums = document.getElementById("snb_secondary_function_numbers");
form.host_options = document.getElementById("snb_host_options");
form.site_locs_div = document.getElementById("site_locations_div");
form.site_locs = document.getElementById("snb_site_locations");
form.dc_or_off_prem_div = document.getElementById("dc_or_off_premise_div");
form.dc_off_prem_codes = document.getElementById("snb_dc_offpremise_codes");
var snb_secondary_activity_codes = "";
var snb_primary_function_codes = "";
var snb_secondary_function_codes = "";
var snb_secondary_function_numbers = "";
var snb_host_options = "";
var snb_site_locations = "";
var snb_dc_op = "";
//builds the server location hosting options selection
function buildLocationTypeSelector() {
var locationOptionsString = "<option value='0' disabled selected>Select Option</option>";
for (var i = 0; i < locationOptions.length; i++) {
var location = locationOptions[i];
locationOptionsString += "<option value=" + location.hostLocale + " data-code=" + location.code + ">" + location.hostLocale + "</option>";
}
$("#snb_host_options").append(locationOptionsString);
}
function buildSiteLocations(bigString){
if(bigString === undefined){
var siteLocs = document.getElementById("snb_site_locations");
var newOption = document.createElement("option");
newOption.setAttribute("value", 0);
newOption.setAttribute("disabled","disabled");
newOption.setAttribute("checked","checked");
var newText = document.createTextNode("Select Option");
newOption.appendChild(newText);
siteLocs.appendChild(newOption);
} else{
var siteLocs = document.getElementById("snb_site_locations");
siteLocs.innerHTML = bigString;
}
}
return {
form:form,
buildSelectSiteLocations: function(bigString){
buildSiteLocations(bigString);
},
buildForm: function (osType, optObj) {
buildLocationTypeSelector();
buildSecondaryFunctionNumberSelector();
buildSiteLocations();
if(osType === 'windows'){
$("#snb_secondary_activity_codes").append(optObj.windows.secondary_activity);
$("#snb_primary_function_codes").append(optObj.windows.primary_function);
$("#snb_secondary_function_codes").append(optObj.windows.secondary_function);
$("#snb_site_locations").append(optObj.windows.site_location);
$("#snb_dc_offpremise_codes").append(optObj.windows.dc_offpremise);
}else{
$("#snb_secondary_activity_codes").append(optObj.unix.secondary_activity);
$("#snb_primary_function_codes").append(optObj.unix.primary_function);
$("#snb_secondary_function_codes").append(optObj.unix.secondary_function);
$("#snb_site_locations").append(optObj.unix.site_location);
$("#snb_dc_offpremise_codes").append(optObj.unix.dc_offpremise);
}
}
};
})();
Thanks in advance.
I work with Twitch API. If the streamer streams I work with with property "Stream". But If he's not streaming, then I need refer to another link. Then I again turn to the function of the getJSON and pass there the necessary API link. And I'm working with her. However, the loop does not work as it should. It takes the last streamer out of the "channels" array, but it should all those who do not stream. I can not understand what the problem is. Help...
JSFiddle: https://jsfiddle.net/e7gLL25y/
JS Code:
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = function() {
if(xhr.readyState == 4 && xhr.status == "200") {
callback(JSON.parse(xhr.responseText));
}
};
xhr.send();
};
var channels = ["summit1g", "esl_RuHub_CSGO", "Starladder1", "Senpai_Frozen", "tehvivalazz", "ESL_CSGO"];
var client_id = "hx3dea4ifwensxffoe8iwvekwvksnx";
var section = document.getElementById("main-section");
var streamer = [];
for(var i = 0; i < channels.length; i++) {
var url_channels = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=" + client_id;
var url_streams = "https://api.twitch.tv/kraken/streams/" + channels[i] + "?client_id=" + client_id;
getJSON(url_streams, function(response) {
if( response["stream"] !== null ) {
streamer[i] = document.createElement("div");
streamer[i].className = "streamer";
streamer[i].innerHTML = "<a target='_blank' href='" + response.stream.channel["url"] +
"'><img id='streamer-image' src='" +
response.stream.channel["logo"] +
"' alt='Av' /><h2 id='streamer-name'>" +
response.stream.channel["name"] +
"</h2><p id='stream-status'>" +
response.stream["game"] + "</p></a>";
section.appendChild(streamer[i]);
} else {
getJSON(url_channels, function(r) {
streamer[i] = document.createElement("div");
streamer[i].className = "streamer";
streamer[i].innerHTML = "<a target='_blank' href='" + r["url"] +
"'><img id='streamer-image' src='" +
r["logo"] +
"' alt='Av' /><h2 id='streamer-name'>" +
r["name"] +
"</h2><p id='stream-status'>Offline</p></a>";
section.appendChild(streamer[i]);
});
}
});
}
You are having a common misconception about JavaScript contexts.
Refer to my answer here to see details about this problem: https://stackoverflow.com/a/42283571/1525495
Simply, the getJSON response is called after all the array is looped, so i will be the last index in all the responses. You have to create another context to keep the i number so is not increased.
for(var i = 0; i < channels.length; i++) {
var url_channels = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=" + client_id;
var url_streams = "https://api.twitch.tv/kraken/streams/" + channels[i] + "?client_id=" + client_id;
(function(i) {
// i will not be changed by the external loop as is in another context
getJSON(url_streams, function(response) {
// Thingy things...
});
})(i);
}