Javascript onclick dynamic for loop get a hold of index - javascript

Hello I have a problem gettig a hold of the index in the following code:
Contacts.push("test1 test 4232352");
Contacts.push("test2 test2 5435345");
for(var i = 0; i < Contacts.length; i++){
var res = Contacts[i].split(" ");
var font = document.createElement("FONT");
font.innerHTML = res[0] + " " + res[1];
font.style.marginLeft = "10px";
font.onclick = () => { console.log(i); };
document.getElementById("contacts_collection").appendChild(font);
}
in my mind it should print the index of the element I click on, but instead nomatter which of the 2 I click, it always prints '2'.

The problem is the delclaration of i using the statement var.
An alternative is declaring i using the statement let:
for(let i = 0; i < Contacts.length; i++){}
^^^
Or, you can use IIFE to keep the current value of i:
var Contacts = ["test1 test 4232352", "test2 test2 5435345"];
for (var i = 0; i < Contacts.length; i++) {
var res = Contacts[i].split(" ");
var font = document.createElement("FONT");
font.innerHTML = "<b>" + res[0] + " " + res[1] + "</b>";
font.style.marginLeft = "10px";
font.onclick = ((index) => () => {
console.log(index);
})(i);
document.body.appendChild(font);
}

You can also use the forEach() for your array.
DEMO
In ES5
var Contacts = ["test1 test 4232352", "test2 test2 5435345"],
font = '';
Contacts.forEach(function(v, i) {
v = v.split(" ");
font = document.createElement("FONT");
font.innerHTML = '<b>' + v[0] + ' ' + v[1] + ' </b><br>';
font.setAttribute("style", "margin-left:10px; cursor:pointer");
font.index = i;
font.onclick = function(e) {
console.log(e.target.parentElement.index);
};
document.getElementById('mydiv').appendChild(font);
});
<div id="mydiv"></div>
In ES6
const Contacts = ["test1 test 4232352", "test2 test2 5435345"];
Contacts.forEach((v, i) => {
v = v.split(" ");
let font = document.createElement("FONT");
font.innerHTML = `<b>${v[0]} ${v[1]}</b><br>`;
font.setAttribute("style", "margin-left:10px; cursor:pointer");
font.index = i;
font.onclick = (e => {
console.log(e.target.parentElement.index);
});
document.getElementById('mydiv').appendChild(font);
});
<div id="mydiv"></div>
You can also use for...in statement for array iterates.
DEMO
var Contacts = ["test1 test 4232352", "test2 test2 5435345"],
font = '',v;
for(let i in Contacts){
v = Contacts[i].split(" ");
font = document.createElement("FONT");
font.innerHTML = '<b>' + v[0] + ' ' + v[1] + ' </b><br>';
font.setAttribute("style", "margin-left:10px; cursor:pointer");
font.index = i;
font.onclick = function(e) {
console.log(e.target.parentElement.index);
};
document.getElementById('mydiv').appendChild(font);
};
<div id="mydiv"></div>

Related

GAS/ Javascript giving wrong figures when summing up numbers

My Javascript/GAS code uses the user ID to call for time entries via API for a specific date range (1 week) and sum up the hours. These time entries are saved in an array and then summed up. The first 50 additions on the log are correct but as you go through the list you realize wrong summed figures and long decimal places. What could be wrong and what can I do to solve this. Here is my code:
var TKF_URL = 'https://api.10000ft.com/api/v1/';
var TKF_AUTH = 'auth'
var TKF_PGSZ = 2500
var from = '2020-01-06'
var to = '2020-01-22'
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + TKF_AUTH
}
};
function getUsers() {
var userarray = [];
var lastpage = false;
var page = 1;
do {
// gets 10kft data
var users = read10k_users(page);
// writes data from current page to array
for (var i in users.data) {
var rec = {};
// pushing of mandatory data
rec.id = users.data[i].id;
rec.display_name = users.data[i].display_name;
rec.email = users.data[i].email;
userarray.push(rec);
}
// checks if this is the last page (indicated by paging next page link beeing null
if (users.paging.next != null) {
lastpage = false;
var page = page + 1;
} else {
lastpage = true;
}
}
while (lastpage == false);
return (userarray);
return (userarray);
}
function read10k_users(page) {
var endpoint = 'users?';
var url = TKF_URL + endpoint + 'per_page=' + TKF_PGSZ + '&auth=' + TKF_AUTH + '&page=' + page;
var response = UrlFetchApp.fetch(url, options);
var json = JSON.parse(response);
//Logger.log(json.data)
return (json);
}
function showTimeData() {
var users = getUsers()
var endpoint = 'users/';
var time_array = [];
for (var i = 0; i < users.length; i++) {
var total_hours = 0;
// Logger.log(users[i].id)
var url = 'https://api.10000ft.com/api/v1/users/' + users[i].id + '/time_entries?fields=approvals' + '&from=' + from + '&to=' + to + '&auth=' + TKF_AUTH;
var response = UrlFetchApp.fetch(url, options);
var info = JSON.parse(response.getContentText());
var content = info.data;
for (var j = 0; j < content.length; j++) {
total_hours += content[j].hours;
// }
//
// if(total_hours < 35){
//
// sendMail(user[i]);
//
// }
Logger.log('User name: ' + users[i].display_name + ' ' + 'User id: ' + users[i].id + ' ' + 'total hours: ' + total_hours)
}
}
function sendMail(user) {
var emailAddress = user.email;
var message = 'Dear ' + user.display_name + 'Your timesheets is incomplete , please visist 10k Ft and commlete your timesheet'
var subject = 'TimeSheet';
MailApp.sendEmail(emailAddress, subject, message);
}
}
Log results
You have total_hours declared outside of your loop. So what you are doing is calculating the total hours all workers combined, not total hours per worker.
(removed a lot of code to show only the important parts for your bug)
function showTimeData() {
var users = getUsers()
var total_hours = 0; // you declare the variable here
for (var i = 0; i < users.length; i++) {
var content = info.data;
// Calculate the sum for current user
for (var j = 0; j < content.length; j++) {
total_hours += content[j].hours;
}
// Check if total_hours for ALL workers is less than 35
if (total_hours < 35) sendMail(user[i]);
// total_hours is not reset, so the sum is used in next iteration.
}
}
Move the declaration of total_hours to inside the loop, or reset it to zero.
function showTimeData() {
for (var i = 0; i < users.length; i++) {
var total_hours = 0; // you declare the variable here
}
}
Your loop should look something like this:
for (var i = 0; i < users.length; i++) {
var total_hours = 0;
var url = "https://api.10000ft.com/api/v1/users/" + users[i].id + "/time_entries?fields=approvals" + "&from=" + from + "&to=" + to + "&auth=" + TKF_AUTH;
var response = UrlFetchApp.fetch(url, options);
var info = JSON.parse(response.getContentText());
var content = info.data;
for (var j = 0; j < content.length; j++) {
total_hours += content[j].hours;
}
if (total_hours < 35) {
sendMail(user[i]);
}
Logger.log("User name: " + users[i].display_name + " " + "User id: " + users[i].id + " " + "total hours: " + total_hours);
}

Removing random element from an array /Javascript

I googled my question but found no answer, thank you in advance for help. The thing is, I have some code that works ok, but I would like to improve it:
function go(times) {
function pick(n) {
return n[Math.floor(Math.random() * n.length)];
}
var body = ["face", "nose", "hair", "smile"];
var adj = ["amazing", "nice", "beautiful", "perfect"];
var word = ["great", "innocent", "glowing", "adorable"];
var str = "Your " + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
if (times > 0) {
for (i = 0; i < times; i++) {
str = str + " And " + go().toLowerCase();
}
}
return str;
}
When the random word is picked, it should be removed from an array so there won't be any repeation. I can handle it with splice function if I know exact index of element, but when it's random it doesn't work how I want it to.
You can easily add a function to all arrays to return a random value and/or remove one randomly.
// After this, you can call.getRandomValue() on any array!
Array.prototype.getRandomValue = function(removeItem) {
if (this.length < 1) throw "Cannot get random value from zero-length array";
var randomIndex = Math.floor(Math.random() * this.length);
var randomValue = this[randomIndex];
if (removeItem)
this.splice(randomIndex, 1);
return randomValue;
};
function constructDescription(sentenceCount) {
var body = ["face", "nose", "hair", "smile"];
var adj = ["amazing", "nice", "beautiful", "perfect"];
var word = ["great", "innocent", "glowing", "adorable"];
var description = "";
for(var i = 0; i < sentenceCount; i++) {
if (body.length > 0 && adj.length > 0 && word.length > 0) {
description += (description.length > 0) ? " And your " : "Your ";
description += body.getRandomValue(true) + " looks " + adj.getRandomValue(true) + " and " + word.getRandomValue(true) + "!"
}
}
return description;
}
Try it out with a Fiddle here.
Use a different function instead of calling go() recursively in the loop. By calling go() for each phrase you initialize the original arrays each time. Then do the splicing in pick()
function go(times) {
var body = ["face", "nose", "hair", "smile"];
var adj = ["amazing", "nice", "beautiful", "perfect"];
var word = ["great", "innocent", "glowing", "adorable"];
var str = ''
function pick(n) {
var idx = Math.floor(Math.random() * n.length);
var str = n[idx];
n.splice(idx, 1)
return str;
}
function getPhrase(i) {
var phrase = pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
return i == 0 ? "Your " + phrase : " And your " + phrase;
}
for (var i = 0; i < times; i++) {
str += getPhrase(i);
}
return str;
}
document.body.innerHTML = go(4);
You just need to combine your splice and your randomizer. example:
function go(times) {
var body = ["face", "nose", "hair", "smile"];
var adj = ["amazing", "nice", "beautiful", "perfect"];
var word = ["great", "innocent", "glowing", "adorable"];
function pick(n) {
return n.splice(Math.floor(Math.random() * n.length), 1);
}
var str = "";
for (var i = 0; i < times; i++) {
str += (i > 0 ? " And your ":"Your ") + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
}
return str;
}
#lucounu solution is absolutely spot on.
In case if you just wanted to improve upon your initial solution , you could have done the following :
var body = ["face", "nose", "hair", "smile"];
var adj = ["amazing", "nice", "beautiful", "perfect"];
var word = ["great", "innocent", "glowing", "adorable"];
function go(times) {
function pick(n) {
var index = Math.floor(Math.random() * n.length)
var randomString = n[index];
n.splice(index,1);
return randomString;
}
var str = "Your " + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
if (times > 0) {
for (i = 0; i < times; i++) {
str = str + " And " + go().toLowerCase();
}
}
return str;
}
console.log(go(2));
Give it a try
var data = ["brain", "mitochondria", "microsope", "beaker", "beaker-2", "scientist", "cell", "atom"];
while (data.length) {
document.write(data.splice(data.length * Math.random() | 0, 1)[0] + '<br>');
}

Internet Explorer gives error: ')' is expected, while firefox isn't?

Internet Explorer gives an error ')' is expected while Firefox is running this code fine. According to the Internet Explorer console the error is situated in the first line:
function HTMLtableRows (titles=[] , values=[]) {
How can I fix this problem?
function HTMLtableRows (titles=[] , values=[]) {
var i, j;
var str, strT, strM;
str = '<table class="table">';
str = str + '<tr>';
for (j = 0; j < titles.length; j++) {
str = str + '<th colspan="2"><center>' + titles[j] + '</center></th>';
}
str = str + '</tr>' + '<tr>';
for (j = 0; j < titles.length; j++) {
str = str + '<th>Tijdstip</th>' + '<th>Looptijd</th>';
}
str = str + '</tr>' + '<tr>';
for (j = 0; j < titles.length; j++) {
var a = values[j].split('\r');
strT = ''
strM = ''
for (i = 0; i < a.length; i++) {
var b = a[i].split('=');
if (b[1] != undefined) {
strT = strT + b[0];
strM = strM + b[1] + 'min';
}
if (i < a.length - 1) {
strT = strT + '<br>';
strM = strM + '<br>';
}
}
str = str + '<td>' + strT + '</td>';
str = str + '<td>' + strM + '</td>';
}
str = str + '</tr>';
str = str + '</table>';
return str;
}
IE does not support default parameters.
Just do it like this if you want
function HTMLtableRows (titles , values) {
if (!titles) titles = [];
if (!values) values = [];
console.log(titles);
console.log(values);
}
a1 = [1,2,3];
HTMLtableRows(a1, null);
HTMLtableRows({foo: "bar"}, undefined);
HTMLtableRows(2, NaN);
HTMLtableRows("not empty string", "");
HTMLtableRows(1, 0);
HTMLtableRows(true, false);
All of the following values
null
undefined
NaN
""
0
false
will become an empty array. If you don't want some of those values to be overwritten with an empty array adjust if conditions as you see fit.
Example where you allow values to remain unchanged as "", 0 and NaN:
function HTMLtableRows (titles , values) {
if (!titles) titles = [];
if(values != "" &&
values != 0 &&
!isNaN(parseInt(values))
)
values = [];
console.log(titles);
console.log(values);
}
HTMLtableRows("string", "");
HTMLtableRows(1, 0);
HTMLtableRows(7, NaN);
Thanks to alex i've solved this with the adjustments below:
function HTMLtableRows (tmpTitles , tmpValues) {
titles=[];
values=[];
titles = tmpTitles;
values = tmpValues;
//...
}

Unexpected end of input JavaScript

Can somebody please tell me what is wrong with the JavaScript in this code? It said "Unexpected end of input", but I do not see any errors. All my statements seem to be ended at some point, and every syntax checker says that no errors were detected.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<title>Slide Editor</title>
<style>
#font-face {
font-family: SegoeUILight;
src: url(Segoe_UI_Light.ttf);
}
* {
font-family: SegoeUILight;
}
</style>
<script src="Slide/RevealJS/lib/js/html5shiv.js"></script>
<script src="Slide/RevealJS/lib/js/head.min.js"></script>
</head>
<body onload="editSlideshow()">
<div id="sl">
<span id="sls"></span>
</div>
<span id="slt"></span>
<div id="editor">
</div>
<script>
function getURLParameters(paramName) {
var sURL = window.document.URL.toString();
if (sURL.indexOf("?") > 0) {
var arrParams = sURL.split("?");
var arrURLParams = arrParams[1].split("&");
var arrParamNames = new Array(arrURLParams.length);
var arrParamValues = new Array(arrURLParams.length);
var i = 0;
for (i = 0; i < arrURLParams.length; i++) {
var sParam = arrURLParams[i].split("=");
arrParamNames[i] = sParam[0];
if (sParam[1] != "")
arrParamValues[i] = unescape(sParam[1]);
else
arrParamValues[i] = "No Value";
}
for (i = 0; i < arrURLParams.length; i++) {
if (arrParamNames[i] == paramName) {
//alert("Parameter:" + arrParamValues[i]);
return arrParamValues[i];
}
}
return "No Parameters Found";
}
}
var name = getURLParameters("show");
var slideCount = 1;
function editSlideshow() {
if (localStorage.getItem("app_slide_doc_" + name) == null) {
$("#sls").append('<button onclick = "loadSlide\'1\')" id = "slide_1">Slide 1</button>');
$("#sl").append('button onclick = "newSlide()">New Slide</button>');
slideCount = 1;
} else {
var textArray = JSON.parse(localStorage.getItem("app_slide_doc_" + name));
slideCount = textArray.length;
var slideCnt = textArray.length - 1;
for (var i = 0; i <= slideCnt; i++) {
$("#sls").append('<button onclick = "loadSlide\'' + (i + 1) + '\')" id = "slide_' + (i + 1) + '">Slide ' + (i + 1) + '</button>');
};
$("sl").append('<button onclick = "newSlide()">New Slide</button>');
};
};
function loadSlide(num) {
var array = JSON.parse(localStorage.getItem("app_slide_doc_" + name));
if (array == null) {
document.getElementById("editor").innerHTML = "<p><textarea rows = '15' cols = '100' id = 'editTxt'></textarea></p>";
document.getElementById("slt").innerHTML = "Slide " + num;
$("#editor").append("<p><button onclick = 'saveSlide(\"" + num + "\")'>Save Slide</button><button onclick = 'deleteSlide(\"" + num + "\")'>Delete Slide</button></p>");
} else if (array[num - 1] == null) {
document.getElementById("editor").innerHTML = "<p><textarea rows = '15' cols = '100' id = 'editTxt'></textarea></p>";
document.getElementById("slt").innerHTML = "Slide " + num;
$("#editor").append("<p><button onclick = 'saveSlide(\"" + num + "\")'>Save Slide</button><button onclick = 'deleteSlide(\"" + num + "\")'>Delete Slide</button></p>");
} else {
var slideArray = JSON.parse(localStorage.getItem("app_slide_doc_" + name));
var text = slideArray[num - 1];
document.getElementById("editor").innerHTML = "<p><textarea rows = '15' cols = '100' id = 'editTxt'></textarea></p>";
document.getElementById("editTxt").value = text;
document.getElementById("slt").innerHTML = "Slide " + num;
$("#editor").append("<p><button onclick = 'saveSlide(\"" + num + "\")'>Save Slide</button><button onclick = 'deleteSlide(\"" + num + "\")'>Delete Slide</button></p>");
};
};
function saveSlide(num) {
if (localStorage.getItem("app_slide_doc_" + name) == null) {
var text = document.getElementById("editTxt").value;
var textArray = new Array();
textArray[num - 1] = text;
localStorage.setItem("app_slide_doc_" + name, JSON.stringify(textArray));
} else {
var textArray = JSON.parse(localStorage.getItem("app_slide_doc_" + name));
var text = document.getElementById("editTxt").value;
textArray[num - 1] = text;
localStorage.setItem("app_slide_doc_" + name, JSON.stringify(textArray));
};
};
function newSlide() {
var nextSlide = slideCount + 1;
$("#sls").append('<button onclick = "loadSlide(\'' + nextSlide + '\')" id = "slide_' + nextSlide.toString() + '">Slide ' + nextSlide.toString() + '</button>');
slideCount = nextSlide;
};
function deleteSlide(num) {
if (localStorage.getItem("app_slide_doc_" + name) == null) {
if (num !== "1") {
$("#slide_" + num).remove();
document.getElementById("editor").innerHTML = "";
document.getElementById("slt").innerHTML = "";
slideCount = slideCount - 1;
location.reload();
} else {
alert("The first slide cannot be deleted.");
};
} else {
var textArray = JSON.parse(localStorage.getItem("app_slide_doc_" + name));
if (num !== "1") {
$("#slide_" + num).remove();
document.getElementById("editor").innerHTML = "";
document.getElementById("slt").innerHTML = "";
slideCount = slideCount - 1;
textArray.splice((num - 1), 1);
localStorage.setItem("app_slide_doc_" + name, JSON.stringify(textArray));
location.reload();
} else {
alert("The first slide cannot be deleted.");
};
};
};
</script>
</body>
</html>
You've gotten the punctuation wrong in more than one of your onclick attributes, for instance here:
$("#sls").append('<button onclick = "loadSlide\'1\')" id = "slide_1">Slide 1</button>');
It's missing the opening parenthesis. The reason syntax checks don't immediately catch this is because you're putting code inside a string. Which you should not do.
Since you're using jQuery, how about using .click(function() { ... }) instead of inline attributes? Just be careful to get your captured variables correct.
The problem at line 63
$("#sl").append('button onclick = "newSlide()">New Slide</button>');
Should be:
$("#sl").append('<button onclick = "newSlide()">New Slide</button>');

Dynamic variable key value pair array

Is there a way to dynamically assign an array? The code doesn't work as intended. It fails at var p = { z }
var z = "\"" + m[0] + "\"" + " : " + "\"" + (m[0] = m[1]) + "\"";
if(i != u.length - 1){
z = z + ",";
}
var p = {z}
for (var key in p) {
if (p.hasOwnProperty(key)) {
client = Elements.AddNew(key, p[key]);
client.Update();
}
}
Entire code
var fso, f1, ts, s;
var ForReading = 1;
fso = new ActiveXObject("Scripting.FileSystemObject");
// Read the contents of the file.
Session.Output("Reading file");
ts = fso.OpenTextFile("c:\\temp\\roles.txt", ForReading);
s = ts.ReadAll();
u = s.split('\r\n');
Session.Output(u);
for(i = 0; i < u.length; i++){
m = u[i].split(",");
var z = "\"" + m[0] + "\"" + " : " + "\"" + (m[0] = m[1]) + "\"";
if(i != u.length - 1){
z = z + ",";
}
var p = {
z
}
Session.Output(p);
for (var key in p)
{
if (p.hasOwnProperty(key))
{
client = Elements.AddNew(key, p[key]);
client.Update();
}
}
}
The contents of the file are as follows. It's a comma delimited file.
abc,1
def,2
ghi,3
You can't create an object like that.
You need to use bracket notation as the member operator to do this
var p = {}
p[m[0]] = m[1];
for (var key in p) {
if (p.hasOwnProperty(key)) {
client = Elements.AddNew(key, p[key]);
client.Update();
}
}
I'll assume that:
(m[0] = m[1])
should have been:
(m[0] == m[1])
If you have an array m that is like:
var m = ['a', 'b', 'b'];
you seem to be trying to make an object using the pattern:
var z = { m[0] : (m[0] == m[1]) };
which can be written:
var z = {};
z[m[0]] = m[0] == m[1];
An object can be created from the array using:
var z = {};
for (var i=0, iLen=m.length - 1; i<iLen; i++) {
z[m[i]] = m[i] == m[i+1];
}
Which will create an object like:
{a: false, b: true}

Categories