Get argument of executed function in function Javascript - javascript

I have a function that measures time execution of function, and cleans DOM after each execution:
function measureTimeExecution(domID, testFunc){
console.time("timer");
for(var i = 0; i < 10; i++){
testFunc();
var getDiv = document.getElementById(domID);
}
getDiv.empty();
console.timeEnd("timer");
}
Function that creates new ul
function createList_Task_2(divID){
var createNewUL = document.createElement("ul");
createNewUL.id = "phoneList";
document.getElementById(divID).appendChild(createNewUL);
for(var i = 0; i < phones.length;i++){
var chunk = "<li>" + phones[i].age +"<br>" + phones[i].id +"<br><img src='"
+ phones[i].imageUrl +"'/><br>" + phones[i].name + "<br>" + phones[i].snippet + "</li>";
document.getElementById("phoneList").innerHTML += chunk;
}
}
But iy gives me: Uncaught TypeError: testFunc is not a function;
Example:
measureTimeExecution("div1", createList_Task_3("div1"));
Is it possible to get somehow domID in measureTimeExecution as a argument of testFunc?

the problem is that when you are calling measureTimeExecution you are runing the parameter, instead pass a function again.
look at this code it should work
measureTimeExecution("div1", function () { createList_Task_3("div1"); });

function measureTimeExecution(domID, testFunc)
The function expects the second argument to be a function, but calling it like measureTimeExecution("div1", createList_Task_3("div1"));, it provides the return of createList_Task_3("div1"). Since createList_Task_3 returns nothing, the default return is undefined.
For it to be a function as well as be able to be provided the ID, it should return a function like this:
function createList_Task_2(divID){
return function(){
var createNewUL = document.createElement("ul");
createNewUL.id = "phoneList";
document.getElementById(divID).appendChild(createNewUL);
for(var i = 0; i < phones.length;i++){
var chunk = "<li>" + phones[i].age +"<br>" + phones[i].id +"<br><img src='"
+ phones[i].imageUrl +"'/><br>" + phones[i].name + "<br>" + phones[i].snippet + "</li>";
document.getElementById("phoneList").innerHTML += chunk;
}
}
}

Related

JS Function Scope with Ebay API

js beginner here. the ebay website has sample code for sending an api request with javascript. the code works out of the box, but the code breaks when i wrap the entire code inside of:
(document).ready( function() {
('button').click( function() {
//(ebays sample code here)
}); });
google chromes console says my error is:
Uncaught ReferenceError: _cb_findItemsByKeywords is not defined
at http://svcs.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsByKeywords&SERVICE-VERSION=1.0.0&SECURITY-APPNAME=micahelr-layitont-PRD-f51ca6568-6366e278&GLOBAL-ID=EBAY-US&RESPONSE-DATA-FORMAT=JSON&callback=_cb_findItemsByKeywords&REST-PAYLOAD&keywords=accord&paginationInput.entriesPerPage=5&itemFilter(0).name=MaxPrice&itemFilter(0).value=30&itemFilter(0).paramName=USD&itemFilter(1).name=ListingType&itemFilter(1).value(0)=AuctionWithBIN&itemFilter(1).value(1)=FixedPrice:1:5
(anonymous) # svcs.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsByKeywords&SERVICE-VERSION=1.0.0&SECURITY-APPNAME=micahelr-layitont-PRD-f51ca6568-6366e278&GLOBAL-ID=EBAY-US&RESPONSE-DATA-FORMAT=JSON&callback=_cb_findItemsByKeywords&REST-PAYLOAD&keywords=accord&paginationInput.entriesPerPage=5&itemFilter(0).name=MaxPrice&itemFilter(0).value=30&itemFilter(0).paramName=USD&itemFilter(1).name=ListingType&itemFilter(1).value(0)=AuctionWithBIN&itemFilter(1).value(1)=FixedPrice:1
what i have come up with, is that the scope of my callback function is incorrect. ive moved the .ready() and .click() statements in many different places within the script tags, trying to solve the problem without completely understanding how it can be fixed. i tried reading about function scope but it seems like its something that i just cant figure out. the following is the content of mt HTML file with embedded JS code:
<html>
<head>
</head>
<body>
<button>click</button>
<script>
$(document).ready(function() {
$('button').click( function() {
var urlfilter = "";
item_MaxPrice = Number(document.getElementById('pagePrice').innerHTML);
inputKeywords = 'accord';
var filterarray = [ {"name":"MaxPrice", "value":item_MaxPrice, "paramName":"USD"}, ];
function _cb_findItemsByKeywords(root) {
var items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
var html = [];
html.push('<table width="100%" border="0" cellspacing="0" cellpadding="3">
for (var i = 0; i < items.length; ++i) {
var item = items[i];
html.push('text here');};
document.getElementById("results").innerHTML = html.join("");};
// Generates an indexed URL snippet from the array of item filters
function buildURLArray() {
for(var i=0; i<filterarray.length; i++) {
var itemfilter = filterarray[i];
for(var index in itemfilter) {
if (itemfilter[index] !== "") {
if (itemfilter[index] instanceof Array) {
for(var r=0; r<itemfilter[index].length; r++) {
var value = itemfilter[index][r];
urlfilter += "&itemFilter\(" + i + "\)." + index + "\(" + r + "\)=" + value ;
}
}
else {
urlfilter += "&itemFilter\(" + i + "\)." + index + "=" +
itemfilter[index];
}}}}}
// Execute the function to build the URL filter
buildURLArray(filterarray);
var url = "http://svcs.ebay.com/services/search/FindingService/v1";
url += "?OPERATION-NAME=findItemsByKeywords";
url += "&SERVICE-VERSION=1.0.0";
url += "&SECURITY-APPNAME=micahelr-layitont-PRD-f51ca6568-6366e278";
url += "&GLOBAL-ID=EBAY-US";
url += "&RESPONSE-DATA-FORMAT=JSON";
url += "&callback=_cb_findItemsByKeywords";
url += "&REST-PAYLOAD";
url += "&keywords="+inputKeywords;
url += "&paginationInput.entriesPerPage=5";
url += urlfilter;
s=document.createElement('script'); // create script element
s.src= url;
document.body.appendChild(s);
document.write("<a href='" + url + "'>" + url + "</a>");
})});
</script>
</body>
<footer>©darnell cross 2018</footer>
</html>
Uncaught ReferenceError: _cb_findItemsByKeywords is not defined
You are getting this error because Javascript can't find the _cb_findItemsByKeywords function.
What is the problem?
You are creating a script element and adding it to the DOM which is having _cb_findItemsByKeywords function as a callback in the URL.
s=document.createElement('script'); // create script element s.src=
url; document.body.appendChild(s); document.write("" + url + "");
Now, the script would run in the global context and wouldn't find any _cb_findItemsByKeywords function there because you defined it inside of another function.
$(document).ready(function() {...}
(Remember: Every function creates it's own context)
Solution:
Add the _cb_findItemsByKeywords function to the window object.
window._cb_findItemsByKeywords = function() {...}
Hopefully this helps you understand scope with indentation levels. Normally when you indent you use it to help you visualize the levels of scope. A variable declared in a parent scope can be accessed in the child but not the other way around.
<html>
<head>
</head>
<body>
<button>click</button>
<script>
$(document).ready(function() {
$('button').click(function() {
//start of scope
var urlfilter = "";
item_MaxPrice = Number(document.getElementById('pagePrice').innerHTML);
inputKeywords = 'accord';
var filterarray = [{
"name": "MaxPrice",
"value": item_MaxPrice,
"paramName": "USD"
}, ];
function _cb_findItemsByKeywords(root) {
var items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
var html = [];
html.push('<table width="100%" border="0" cellspacing="0" cellpadding="3">
for (var i = 0; i < items.length; ++i) {
//start of new scope (can access everything in parent scope but nothing in a scope that is further nested
var item = items[i];
html.push('text here');
//end of new scope
}; document.getElementById("results").innerHTML = html.join("");
};
// Generates an indexed URL snippet from the array of item filters
function buildURLArray() {
for (var i = 0; i < filterarray.length; i++) {
var itemfilter = filterarray[i];
for (var index in itemfilter) {
if (itemfilter[index] !== "") {
if (itemfilter[index] instanceof Array) {
for (var r = 0; r < itemfilter[index].length; r++) {
var value = itemfilter[index][r];
urlfilter += "&itemFilter\(" + i + "\)." + index + "\(" + r + "\)=" + value;
}
} else {
urlfilter += "&itemFilter\(" + i + "\)." + index + "=" +
itemfilter[index];
}
}
}
}
}
// Execute the function to build the URL filter
buildURLArray(filterarray);
var url = "http://svcs.ebay.com/services/search/FindingService/v1";
url += "?OPERATION-NAME=findItemsByKeywords";
url += "&SERVICE-VERSION=1.0.0";
url += "&SECURITY-APPNAME=micahelr-layitont-PRD-f51ca6568-6366e278";
url += "&GLOBAL-ID=EBAY-US";
url += "&RESPONSE-DATA-FORMAT=JSON";
url += "&callback=_cb_findItemsByKeywords";
url += "&REST-PAYLOAD";
url += "&keywords=" + inputKeywords;
url += "&paginationInput.entriesPerPage=5";
url += urlfilter;
s = document.createElement('script'); // create script element
s.src = url;
document.body.appendChild(s);
document.write("<a href='" + url + "'>" + url + "</a>");
})
//end of button scope
});
</script>
</body>
<footer>©darnell cross 2018</footer>
</html>

How to recursively build a list using a callback and iterating through the children?

I'm unsure on how to build this list (which is a string) and then returning as one complete string.
I've worked past my last issue but I think this one is realy bugging me. buildItem() should iterate through item, and then recursively build a list while getting the totalCost from another callback. I know it works asynchronously...
buildItem(data, function(html){
$('#nestable ol').append(html);
});
Should append the 'final' html string that's created from being appended throughout the file.
function buildItem(item, callback) {
getTotalCost(item, function(totalCost) {
var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
if (item.children && item.children.length > 0) {
html += "<ol class='dd-list'>";
$.each(item.children, function (index, sub) {
buildItem(item, function(subHtml){
html += subHtml;
})
})
html += "</ol>";
}
html += "</li>";
callback(html);
});
}
I know that
buildItem(item, function(subHtml){
html += subHtml;
})
shouldn't work since javascript is asynchronous. I'm just not sure on how to return from a recursive function? If I were to do something like
buildItem(item, function(subHtml){
callback(subHtml);
})
You'll get duplicate values because you'll have the starting value and it's children, but since you're also calling it back you'll get the children outside of the starting value. So it'll look like
1
a
b
c
d
e
a
b
c
d
e
So what's the best way to approach a solution? I was thinking of making another function, hypothetically a buildChild(sub) that returned html, but the same issue with asynchronous is going to come up where the return will be undefined. I've read some of the threads where you can handle asynchronous values with callbacks, but I'm not sure on how to do it with recursion here.
getTotalCost is another callback function that shouldn't mean much, I removed the line by accident but I just need the totalCost from a database.
function getTotalCost(item, callback) {
$.ajax({
dataType: "json",
url: "/retrieveData.do?item=" + item.email,
success: function(data) {
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
callback(totalCost);
}
});
}
You can simplify this with promises and async functions:
async function getTotalCost(item) {
const data = await Promise.resolve($.ajax({
dataType: "json",
url: "/retrieveData.do?item=" + item.email
}));
return data.reduce((acc, next) => acc + next.cost, 0);
}
async function buildItem(item) {
const totalCost = await getTotalCost(item);
let html = `<li class="dd-item" data-id="${item.id}" data-email="${item.email}" data-title="${item.corporateTitle}" data-name="${item.firstName} ${item.lastName}" id="${item.id}">`;
if (item.children && item.children.length > 0) {
html += '<ol class="dd-list">';
for (const childItem of item.children) {
html += await buildItem(childItem);
}
html += "</ol>";
}
html += "</li>";
return html;
}
Unfortunately, async functions aren't supported by all browsers yet, so you'll have to use Babel to transpile your code.
I also added some new ES6 features: arrow functions, const and template literals.
You can mix slow ajax requests with logic and recursion if you execute your code via synchronous executor nsynjs.
Step 1. Write your logic as if it was synchronous, and place it into function:
function process(item) {
function getTotalCost(item) {
var data = jQueryGetJSON(nsynjsCtx, "/retrieveData.do?item=" + item.email).data;
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
return totalCost;
};
function buildItem(item) {
const totalCost = getTotalCost(item);
var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
if (item.children && item.children.length > 0) {
html += '<ol class="dd-list">';
for (var i=0; i<item.children.length; i++)
html += buildItem(item.children[i]);
html += "</ol>";
}
html += "</li>";
return html;
};
return buildItem(item);
};
Step 2: run it via nsynjs:
nsynjs.run(process,{},item,function (itemHTML) {
console.log("all done",itemHTML);
});
Please see more examples here: https://github.com/amaksr/nsynjs/tree/master/examples

Uncaught ReferenceError: variable is not defined on onclick function Javascript

Today , i have been read all the topic about this but couldn't come up with a solution that's why i am opening this topic.
This is my function which creates the view and i am trying to have a onclick function which should directs to other javascript function where i change the textbox value.
<script type="text/javascript">
$('#submitbtnamazon')
.click(function(evt) {
var x = document.getElementById("term").value;
if (x == null || x == "" || x == "Enter Search Term") {
alert("Please, Enter The Search Term");
return false;
}
listItems = $('#trackList').find('ul').remove();
var searchTerm = $("#term").val();
var url = "clientid=Shazam&field-keywords="
+ searchTerm
+ "&type=TRACK&pagenumber=1&ie=UTF8";
jsRoutes.controllers.AmazonSearchController.amazonSearch(url)
.ajax({
success : function(xml) {
$('#trackList')
.append('<ul data-role="listview"></ul>');
listItems = $('#trackList').find('ul');
html = ''
tracks = xml.getElementsByTagName("track");
for(var i = 0; i < tracks.length; i++) {
var track = tracks[i];
var titles = track.getElementsByTagName("title");
var artists = track.getElementsByTagName("creator");
var albums = track.getElementsByTagName("album");
var images = track.getElementsByTagName("image");
var metaNodes = track.getElementsByTagName("meta");
//trackId ="not found";
trackIds = [];
for (var x = 0; x < metaNodes.length; x++) {
var name = metaNodes[x]
.getAttribute("rel");
if (name == "http://www.amazon.com/dmusic/ASIN") {
trackId = metaNodes[x].textContent;
trackIds.push(trackId);
}
}
for (var j = 0; j < titles.length; j++) {
var trackId=trackIds[j];
html += '<div class="span3">'
html += '<img src="' + images[j].childNodes[0].nodeValue + '"/>';
html += '<h6><a href="#" onclick="someFunction('
+trackId
+ ')">'
+trackId
+ '</a></h6>';
html += '<p><Strong>From Album:</strong>'
+ albums[j].childNodes[0].nodeValue
+ '</p>';
html += '<p><Strong>Artist Name:</strong>'
+ artists[j].childNodes[0].nodeValue
+ '</p>';
html += '<p><Strong>Title:</strong>'
+ titles[j].childNodes[0].nodeValue
+ '</p>';
/*html += '<p><Strong>Created:</strong>'
+ releaseDate
+ '</p>';*/
html += '</div>'
}
}
//listItems.append( html );
$("#track").html(html);
$("#track").dialog({
height : 'auto',
width : 'auto',
title : "Search Results"
});
// Need to refresh list after AJAX call
$('#trackList ul').listview(
"refresh");
}
});
});
</script>
This is my other function where i change the textbox value. it works actually with other values e.g. when i give hardcoded string value. I can see the value in the console but for some reason it gives me the error like :
here the string starts with B is AsinId where i take from amazon. I am definitely in need of help because i am totally stucked.
Uncaught ReferenceError: B00BMQRILU is not defined 62594001:1 onclick
<script type="text/javascript">
function someFunction(var1) {
tracktextbox = document.getElementsByName("trackId");
for (var i = 0; i < tracktextbox.length; i++) {
tracktextbox[i].value = var1;
}
$('#track').dialog('close');
}
</script>
The problem is '<h6><a href="#" onclick="someFunction('+trackId+ ')">', from the error it is clear that trackId is a string value, so you need to enclose it within "" or ''. So try
'<h6><a href="#" onclick="someFunction(\'' + trackId + '\')">'

How do I access an array value correctly within a callback function?

I am trying to access the value of IDs[i] correctly within a function inside a loop. I have tried the following.
This method logs IDs as a string I think. I try to access it with index but it comes out undefined. See the console.log inside simpleWithAttrPrice function call.
for(i=0; i<IDs.length; i++)
{
console.log("Outside of function Vendor is " + IDs[i]);//logs correctly
var optionSelectionArray = currentlySelectedAttributes(IDs[i]);
simpleWithAttrPrice(optionSelectionArray, function(data) {
//var vendor = IDs[i];
var basePrice = parseFloat(roundDollar(data));
//newPriceArray[vendor][colorSelected]=basePrice;
console.log("Vendor is " + IDs);//"5,3"
console.log("Vendor is " + IDs[i]);//undefined
$j('.details'+IDs[i]+ ' .priceBlock').empty();
$j('.details'+IDs[i]+ ' .priceBlock').append('<span>'+formatCurrency(basePrice,"$")+'</span>');
});
}
I also tried passing ID's into the callback function but it logs "success" (literally)
for(i=0; i<IDs.length; i++)
{
//var vendor = IDs[i];
var optionSelectionArray = currentlySelectedAttributes(IDs[i]);
simpleWithAttrPrice(optionSelectionArray, function(data, IDs) {
//var vendor = IDs[i];
var basePrice = parseFloat(roundDollar(data));
//newPriceArray[vendor][colorSelected]=basePrice;
console.log("Vendor is " + IDs);//logs ID's as "success" ??
$j('.details'+IDs[i]+ ' .priceBlock').empty();
$j('.details'+IDs[i]+ ' .priceBlock').append('<span>'+formatCurrency(basePrice,"$")+'</span>');
});
}
Lastly, I've also tried the following but it appends the price to the same block.
for(i=0; i<IDs.length; i++)
{
var vendor = IDs[i];
var optionSelectionArray = currentlySelectedAttributes(vendor);
simpleWithAttrPrice(optionSelectionArray, function(data) {
var basePrice = parseFloat(roundDollar(data));
//newPriceArray[vendor][colorSelected]=basePrice;
console.log("Vendor is " + vendor); //only logs this once.
$j('.details'+vendor+ ' .priceBlock').empty();//If I take this away, appends both prices to same block
$j('.details'+vendor+ ' .priceBlock').append('<span>'+formatCurrency(basePrice,"$")+'</span>');
});
}
How do I access the array IDs correctly within the callback function?
#Toby Allen Thanks! Your right about that link. For reference this works:
function sendRequest(i) {
var optionSelectionArray = currentlySelectedAttributes(IDs[i]);
simpleWithAttrPrice(optionSelectionArray, function(data) {
//var vendor = IDs[i];
var basePrice = parseFloat(roundDollar(data));
//newPriceArray[vendor][colorSelected]=basePrice;
console.log("Vendor is " + IDs);//"5,3"
console.log("Vendor is " + IDs[i]);//undefined
$j('.details'+IDs[i]+ ' .priceBlock').empty();
$j('.details'+IDs[i]+ ' .priceBlock').append('<span>'+formatCurrency(basePrice,"$")+'</span>');
});
}//end sendRequest
for(i=0; i<IDs.length; i++)
{
sendRequest(i);
}

Javascript for loop problems

So I have the following code which i basically just a JSON string I am using eval to convert to an object. Now, this object has an array of elements that gets displayed to the screen via a for loop:
function DisplayListing(str)
{
var obj = eval("(" + str + ")");
var div = document.getElementById('Response');
for(i=0; i<obj.files.length; i++)
{
div.innerHTML += '<span id="listing' + i + '" class="displayNone"><img src="' + obj.files[i].icon + '"/>' + obj.files[i].name + '</span><br />';
}
}
This works just fine. However, what I want it to do is wait a set interval of time before it continues to the next element. I want to it basically call a function with a timeout, so each element fades onto the screen individually. All attempts so far on cause the last element to execute a function. Any help would be greatly appreciated!
http://jsfiddle.net/SfKNc/
var obj = {files: [1, 2, 3]}; // sample object - use JSON.parse by the way
var div = document.getElementById('Response');
for(var i=0; i<obj.files.length; i++) { // use var!
setTimeout((function(i) {
return function() { // i changes, so create a new function in which i does not change
div.innerHTML +=
'<span id="listing' + i +
'" class="displayNone">' + i +
'</span><br />';
};
})(i), i * 1000); // set timeout to 1000 ms for first item, 2000 for second etc.
}
you have manually create a sleep function something like the below:
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
or you create an empty function and use the setTimeout on it
function sleep()
{
setTimeout(Func1, 3000);
}
Func1(){}
http://www.phpied.com/sleep-in-javascript/

Categories