I'm writing little snippets to learn more about using Javascript with API's, and have stumbled onto another problem I can't figure out on my own. I have a global variable (object?) "coins", read in from the API, and its' data field "symbol". I can use "symbol" to reference the data held there, in part of my code, without any errors. Later in the code, I use it again, and I get an error about it being undefined, despite the fact that the values returned from using it, are both defined, and, what I expected. While we are at it, maybe someone can tell me why I assign values to global variables (declared outside of all of the functions), but the variables when called, are "undefined". To see it in action, visit www.mattox.space/XCR and open up dev tools.
/*
FLOW:
get ALL coins, store NAME and SYMBOL into an object.
loop over the names object comparing to $SYMBOL text from form, return the NAME when found.
hit the API again, with the $NAME added to the URL.
create a table row.
insert data from second API hit, into table row
SOMEWHERE in there, do the USD conversion from BTC.
*/
//var name = getName();
var bitcoinValue = 0;
var coins = new Array;
var form = ""; // Value pulled from the form
var symbol = ""; // "id" on the table
var id = ""; // value pulled from the table at coins[i].id matched to coins[i].symbol
var formSym = "";
var formUSD = 0;
var formBTC = 0;
var form24h = 0;
function run() {
getFormData();
allTheCoins("https://api.coinmarketcap.com/v1/ticker/");
testGlobal();
}
function testGlobal() {
console.log("These are hopefully the values of the global variables");
console.log(formSym + " testGlobal");
console.log(formUSD + " testGlobal");
console.log(formBTC + " testGlobal");
console.log(form24h + " testGlobal");
}
function getFormData(){ //This function works GREAT!
form = document.getElementById("symbol").value //THIS WORKS
form = form.toUpperCase(); //THIS WORKS
}
function allTheCoins(URL) {
var tickerRequest = new XMLHttpRequest();
tickerRequest.open('GET', URL);
tickerRequest.send();
tickerRequest.onload = function() {
if (tickerRequest.status >= 200 && tickerRequest.status < 400) {
var input = JSON.parse(tickerRequest.responseText);
for(var i in input)
coins.push(input[i]);
testFunction(coins);
}
else {
console.log("We connected to the server, but it returned an error.");
}
console.log(formSym + " allTheCoins!"); // NOPE NOPE NOPE
console.log(formUSD) + " allTheCoins!"; // NOPE NOPE NOPE
console.log(formBTC + " allTheCoins!"); // NOPE NOPE NOPE
console.log(form24h + " allTheCoins!"); // NOPE NOPE NOPE
}
}
function testFunction(coins) {
for (var i = 0; i < coins.length; i++) {
if (coins[i].symbol == form) { // But right here, I get an error.
formSym = coins[i].name;
formUSD = coins[i].price_usd;
formBTC = coins[i].price_btc;
form24h = coins[i].percent_change_24h;
console.log(formSym + " testFunction");
console.log(formUSD + " testFunction");
console.log(formBTC + " testFunction");
console.log(form24h + " testFunction");
//DO EVERYTHING RIGHT HERE! On second thought, no, this needs fixed.
}
else if (i > coins.length) {
formSym = "Error";
formUSD = 0;
formBTC = 0;
form24h = 0;
}
}
}
/*
if (24h >= 0) {
colorRED
}
else {
colorGreen
}
*/
here is a possible way of doing it that you can get inspired by. its based on a httpRequest promise that set the headers and method.
let allTheCoins = obj => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open(obj.method || obj.method, obj.url);
if (obj.headers) {
Object.keys(obj.headers).forEach(key => {
xhr.setRequestHeader(key, obj.headers[key]);
});
}
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.statusText);
}
};
xhr.onerror = () => reject(xhr.statusText);
xhr.send(obj.body);
});
};
allTheCoins({
url: "https://api.coinmarketcap.com/v1/ticker/",
method: "GET",
headers: {"Accept-Encoding": "gzip"}
})
.then(data => {
ParseCoins(data);
})
.catch(error => {
console.log("We connected to the server, but it returned an error.");
});
function ParseCoins(data) {
const coins = JSON.parse(data);
const form = getFormVal();/*retrieve form val*/
const id = getTableId(); /*retrieve table id*/
const bitcoinValue = getBitcoinVal();/*retrieve bitcoin Value*/
const final_result = [];
for (let i = 0, len = coins[0].length; i < len; i++) {
const coin = coins[0][i];
for (let ii in coin) {
if (coin.hasOwnProperty(ii)) {
if (coin[ii].symbol == form) {
let element = {
formSym: coin[ii].name,
formUSD: coin[ii].price_usd,
formBTC: coin[ii].price_btc,
form24h: coin[ii].percent_change_24h
};
final_result.push(element);
}
}
}
}
coontinueElseWhere(final_result);
}
Related
I'm binding data to 3 dropdowns by calling a method from another file of javascript. The data source of dropdown loading from IndexedDB.
Data binding JS,
function bindStateData(){
getMstStates("#state");
getMstStates("#drstate");
getMstStates("#cstate");
}
Database manager js,
function getMstStates(state) {
var request = indexedDB.open('AppDatabase', '3')
request.onsuccess = function (e) {
var dbInstance = e.target.result;
let transaction = dbInstance.transaction("MstStates", "readonly");
const statesDetailsStore = transaction.objectStore("MstStates");
stateData = statesDetailsStore.getAll();
stateData.onsuccess = function () {
var MstStatesMap = new Object();
var len = stateData.result.length,
i;
for (i = 0; i < len; i++) {
MstStatesMap[i] = {};
MstStatesMap[i].StateId = stateData.result[i].StateId;
MstStatesMap[i].StateName = stateData.result[i].StateName;
}
callBackOptionItems(MstStatesMap, state);
}
stateData.onerror = function () {
console.log('getMstStates : ' + e);
}
}
request.onerror = function (e) { console.log('getMstStates : ' + e); }
}
function callBackOptionItems(MstOptionMap, objID) {
for (var j in MstOptionMap) {
var k, v
var tem = 0;
for (var i in MstOptionMap[j]) {
if (tem == 0) {
k = MstOptionMap[j][i]
} else {
v = MstOptionMap[j][i];
}
tem++
}
var el = $(objID);
$(el).append('<option value="' + k + '">' + v + '</option>');
}
if (objID == '#select-history') {
$("#select-history").append('<option value="4">Other</option>');
}
}
When I tried to loading data I got the following error,
Uncaught DOMException: Failed to read the 'result' property from 'IDBRequest': The request has not finished.
at IDBRequest.stateData.onsuccess
The same code logic was written in WebSQL, it was running properly, but unfortunately from iOS 13 version websql support has been revoked.
I have resolved this issue. The main culprit line is,
var len = stateData.result.length;
The correct code is as follows,
var _request = statesDetailsStore.getAll();
_request.onsuccess = function (event) {
var MstStatesMap = new Object();
var stateData = event.target.result;
}
Please see my code below, I am interrogating active directory and retrieving back two fields, "name" and "cn". I want to concatenate these in an array and then assign to my drop down list. i.e. name + ' ' + cn. The code below publishes my results wrongly and is displaying all names and cn as individual results i.e. not concatenated.
Can someone advise me and put me in the right direction?
thanks,
George
try
{
// Get LDAP Context
ctx = LdapServices.getLdapContext();
//Specify the search scope
ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
var searchFilter = "(&(objectClass=group))";
//Specify the Base for the search
var searchBase = "ou=Licensed Applications,ou=SCCM Apps,ou=Applications,ou=Groups,dc=XXX,dc=XX,dc=XX";
//initialize counter to total the group members
var totalResults = 0;
//Specify the attributes to return
var returnedAtts=["name", "cn"];
ctls.setReturningAttributes(returnedAtts);
//Search for objects using the filter
var answer = ctx.search(searchBase, searchFilter, ctls);
//Loop through the search results
while (answer.hasMoreElements())
{
var sr = answer.next();
var attrs = sr.getAttributes();
if (attrs != null)
{
try
{
for (var ae = attrs.getAll();ae.hasMore();)
{
var attr = ae.next();
var pos = attr.toString().indexOf(":",0);
var attributeName = attr.toString().substring(0,pos);
var name = "";
var cn = "";
for (var e = attr.getAll();e.hasMore();totalResults++)
{
if(attributeName == "name")
{
name = e.next().replace('SCCM_','');
}
if(attributeName == "cn")
{
cn = e.next();
}
}
listItems.push(name + ' (' + cn + ')');
}
}
catch (e)
{
log("Problem listing items: " + e);
}
}
}
}
catch (e)
{
log("Problem searching directory: " + e);
}
finally
{
// Close LDAP Context
ctx.close();
}
I don't know what javascript library you use to have JNDI like code into, but from the purely LDAP point of view :
An attribute can be multi-valued, so every attributes value are returned in a array, even if single valued (possible exception for the dn), for example :
{
"dn":"cn=user,dc=example,dc=com",
"name":["username"],
"cn":["commonname"]
}
If your library works like JNDI, a way to do it could be :
After the line : var attrs = sr.getAttributes();
if (attrs != null) {
try {
log ("name: " + attrs.get("name").get());
log ("cn: " + attrs.get("cn").get());
} catch (e) {
log ("Problem listing attributes from Global Catalog: " + e);
}
}
I am using javascript to load in data from a XML file. The file is not being loaded in after an if statement that checks the ready state and the status. The ready state brings back 4 and the status brings back 200, so the last condition (the responseXML) should not be null, but for some reason, it remains null and the XML file is not loaded.
function load() {
try {
console.log("in load");
asyncRequest = new XMLHttpRequest();
asyncRequest.addEventListener("readystatechange", function() {
processResponse();
}, false);
asyncRequest.open('GET', 'Catalog.xml', true);
asyncRequest.send(null);
} catch (exception) {
alert("Request Failed");
console.log("failed");
}
}
function processResponse() {
console.log(asyncRequest.readyState + " response" + asyncRequest.status + asyncRequest.responseXML);
if (asyncRequest.readyState == 4 && asyncRequest.status == 200 && asyncRequest.responseXML) {
console.log("found");
var planets = asyncRequest.responseXML.getElementsByTagName("planet");
var name = document.getElementById("planetinfo").value;
console.log(name);
for (var i = 0; i < planets.length; ++i) {
var planet = planets.item(i);
var planetName = planet.getElementsByTagName("name").item(0).firstChild.nodeValue;
if (name == planetName) {
document.getElementById("name").innerHTML = planet.getElementsByTagName("name").item(0).firstChild.nodeValue;
document.getElementById("discovered").innerHTML = planet.getElementsByTagName("discovered").item(0).firstChild.nodeValue;
document.getElementById("distance").innerHTML = planet.getElementsByTagName("distance").item(0).firstChild.nodeValue;
document.getElementById("contact").innerHTML = planet.getElementsByTagName("contact").item(0).firstChild.nodeValue;
document.getElementById("image").innerHTML = "<img src='../images/" + planet.getElementsByTagName("image").item(0).firstChild.nodeValue + "' + '/ width = '250' height = '250'>";
}
}
}
}
This is the code from the javascript file that pertains to the loading of the XML. Opening up the console shows logs that tells me the code does not get past the if statement checking the asyncRequest.
I am creating a HTA application since my environment has restrictions. In any case I am trying to connect to an Access Database through a prototype. This prototype is suppose to get the information from the database but it always returns as "undefined". I am unable to determine as to why this is occurring as i am using the ActiveX controls that open that provider.
The Calling function
Please note that the access drivers are installed, the location is correct and the table does exists with content.
function GetX()
{
var db = new AccessDatabase("I:\\Office\\Access\\Sample.accdb");
db.Connect();
if (db.Status != 0) { return; }
// Remove all
$("#x").empty();
// The Query
var results = db.Select("SELECT x FROM Tracker");
// Get the results length
var arrayLength = results.length;
// Iterate through the results
for (var row = 0; row < arrayLength; row++)
{
$("#x").append("<option id='" + results[row][0] + ">" + results[row][0] + "</option>");
}
db.Disconnect();
}
The prototype object:
function AccessDatabase(databaseSource)
{
try
{
this.Connection = new ActiveXObject("ADODB.Connection");
this.Source = databaseSource;
this.Status = 0;
}
catch (err)
{
createNotification("Danger", "Unable to create ActiveX Control For Microsoft ");
this.Status = err.Number;
}
}
AccessDatabase.prototype.Connect = function()
{
try
{
var provider = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + this.Source;
this.Connection.Open(provider);
}
catch (err)
{
createNotification("Danger", "Database Failed To Connect. Was the Source correct?<br>Details: " + err.message);
this.Status = err.Number;
}
}
AccessDatabase.prototype.Disconnect = function()
{
this.Connection.Close();
}
AccessDatabase.prototype.Select = function (selectQuery)
{
try
{
// Open the recordset
var recordSet = new ActiveXObject("ADODB.Recordset");
recordSet.Open(selectQuery, this.Connection);
// Check for null results
if (recordSet.RecordCount == null || recordSet.RecordCount == -1)
{
createNotification("Error", "No record was found for the query provided <br> Query: <small>"
+ selectQuery + "</small>");
recordSet.Close();
this.Status = -1;
return null;
}
alert("Record Count:" + recordSet.RecordCount);
// Convert To Array
var returnValue = recordSet.GetRows();
recordSet.Close();
// Return the array
return returnValue;
}
catch (err)
{
createNotification("Warning", "Query Could Not Execute Due to an error. <br>Details: " + err.message);
this.Status = err.Number;
}
}
I've a small Greasemonkey script that doesn't include any random part, but its results change with each page reload.
I'm a noob and I'm probably doing something wrong, but I don't know what. I hope you'll be able to help me.
The code is too large and too poorly written to be reproduced here, so I'll try to sum up my situation:
I have a list of links which have href=javascript:void(0) and onclick=f(link_id).
f(x) makes an XML HTTP request to the server, and returns the link address.
My script is meant to precompute f(x) and change the href value when the page loads.
I have a function wait() that waits for the page to load, then a function findLinks() that gets the nodes that are to be changed (with xpath).
Then a function sendRequest() that sends the xhr to the server. And, finally handleRequest() that asynchronously (r.onreadystatechange) retrieves the response, and sets the nodes previously found.
Do you see anything wrong with this idea?
Using a network analyzer, I can see that the request is always sent fine, and the response also.
Sometimes the href value is changed, but sometimes for some links it isn't and remains javascript:void(0).
I really don't see why it works only half the time...
function getUrlParameterFromString(urlString, name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(urlString);
if (results == null) {
return "";
} else {
return results[1];
}
}
function getUrlParameter(name) {
return getUrlParameterFromString(window.location.href, name);
}
function wait() {
var findPattern = "//a";
var resultLinks = document.evaluate(findPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (resultLinks == null || resultLinks.snapshotLength == 0) {
return setTimeout(_wait, 100);
} else {
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
sendRequest(linkId, node);
}
}
}
function sendRequest(linkId, nodeToModify) {
window.XMLHttpRequest ? r = new XMLHttpRequest : window.ActiveXObject && (r = new ActiveXObject("Microsoft.XMLHTTP"));
if (r) {
r.open("POST", "some_url", !0);
r.onreadystatechange = function () {
handleRequest(nodeToModify, linkId, r);
}
r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
r.send(linkId);
}
}
function handleRequest(nodeToModify, num, r) {
if (r.readyState == 4) {
if (r.status == 200) {
console.log('handleRequest() used');
var a = r.responseText;
if (a == null || a.length < 10) {
sendRequest(num, nodeToModify);
} else {
var url = unescape((getUrlParameterFromString(a, "url")).replace(/\+/g, " "));
nodeToModify.setAttribute('href', url);
nodeToModify.setAttribute('onclick', "");
}
} else {
alert("An error occurred: " + r.statusText)
}
}
}
wait();
It looks like that script will change exactly 1 link. Look-up "closures"; this loop:
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
sendRequest(linkId, node);
}
needs a closure so that sendRequest() gets the correct values. Otherwise, only the last link will be modified.
Try:
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
//-- Create a closure so that sendRequest gets the correct values.
( function (linkId, node) {
sendRequest (linkId, node);
}
)(linkId, node);
}