onkeyup event on dynamic array - javascript

Good Evening,
I am having trouble setting up the onkeyup event. I am trying to get it to fire an objects method when a user enters text into the text field. It does not seem to find the object.
I have cut down on the code and have made the following sample:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script>
var ReportModule = new function () {
function ReportObj(id, title) {
this.id = id;
this.title = title;
this.result = "";
this.empno = "";
this.UpdateEmpno = function (empNo, resultBoxID) {
this.empno = empNo;
$(resultBoxID).update("Result: " + empNo);
};
};
var ReportObjArray = new Array();
var test1 = new ReportObj("box1", "First object");
var test2 = new ReportObj("box2", "Second object");
ReportObjArray.push(test1);
ReportObjArray.push(test2);
this.Initialize = function () {
for (i = 0; i < ReportObjArray.length; i++) {
var container = document.createElement("div");
container.id = ReportObjArray[i].id;
container.textContent = ReportObjArray[i].title;
$('#Container').append(container);
var empnoInput = document.createElement("input");
empnoInput.type = "text";
empnoInput.id = ReportObjArray[i].id + "_Empno";
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
ReportObjArray[i].UpdateEmpno(empnoInput.value,empnoInput.id); // <-------- Undefined here
};
$('#' + ReportObjArray[i].id).append(empnoInput);
var container2 = document.createElement("div");
container2.id = ReportObjArray[i].id + "_result";
container2.style.border = "1px solid black";
container2.style.width = "100px";
container2.textContent = "Result:";
$('#' + container.id).append(container2);
};
};
}
</script>
</head>
<body onload="ReportModule.Initialize()">
<div id="Container"></div>
</body>
</html>
Update: It works when searching for the object in the ReportObjArray and matching the correct object. However, I was wondering if there was a more efficient way instead of having to look through the array each time.
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
var target_id = document.getElementById(event.target.id).id;
for (j = 0; j < ReportObjArray.length; j++) {
if (target_id = ReportObjArray[j].id) {
ReportObjArray[j].UpdateEmpno(document.getElementById(event.target.id).value,empnoInput.id);
break;
}
}
};

Wrap your for loop code in a closure:
for (i = 0; i < ReportObjArray.length; i++) {
(function(i) {
// code
})(i);
}
Working JS Fiddle:
http://jsfiddle.net/23vkS/

Related

Convert excel to json but with only one header

I am trying to write an html with JS program that will convert an excel file into json which is does bit it does not format it the way I need to. So basically it spits out when finished
[
{
"imei": "357271093291264"
},
{
"imei": "353094106032150"
},
{
"imei": "353112106434588"
}
]
but what I need is.
[
{
"imei": "357271093291264", "353094106032150", "353112106434588"
}
]
So it is taking imei from cell A1 and using it over and over. I just need it
to keep adding on as I go down the rows.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/read-excel-file#4.x/bundle/read-excel-file.min.js"></script>
</head>
<body>
<div style="margin: auto;width: 50;margin-top: 80px;padding: 30px;background-color: #dedede;">
<h2>Excel to JSON Converter</h2>
<input type="file" id="input" />
<br> <br>
<textarea name="json-data" id="json-data" rows="25" style="width: 100%;"></textarea>
<br><br>
<button id="dl-json">Download JSON File</button>
</div>
<script>
var input = document.getElementById('input');
input.addEventListener('change', function(){
readXlsxFile(input.files[0]).then(function(data){
var i = 0;
var headers = [];
var json_object = [];
data.map((row, index)=> {
if (i == 0){
headers = row;
}
if (i > 0){
var temp = {};
for (var x = 0; x < row.length; x++){
temp[headers[x]] = row[x];
}
json_object.push(temp);
}
i++;
});
document.getElementById('json-data').value = JSON.stringify(json_object, null, 2)
});
document.getElementById('dl-json').onclick = function() {
var json_str = document.getElementById('json-data').value;
downloadObjectAsJson(json_str, '');
}
function downloadObjectAsJson(str, filename){
var data_str = "data:text/json;charset=utf-8," + encodeURIComponent(str);
var anchor = document.createElement('a');
anchor.setAttribute("href", data_str);
anchor.setAttribute("download", filename + ".json");
}
});
</script>
</body>
</html>
I have tried playing around with it and pulling out certain parts and setting different variables to certain values.
The shape of your output doesn't seem to make sense. Do you want the first element in your output array to be a key:value pair such as "headerText":"row2Value", and then the rest just strings?
If so, this should work for you:
var input = document.getElementById("input");
input.addEventListener("change", function () {
readXlsxFile(input.files[0]).then(function (data) {
let exportData = [];
for (i = 1; i < data.length; i++) {
i === 1
? exportData.push({ imei: data[i].toString() })
: exportData.push(data[i].toString());
}
document.getElementById("json-data").value = JSON.stringify(exportData);
});
document.getElementById("dl-json").onclick = function () {
var json_str = document.getElementById("json-data").value;
downloadObjectAsJson(json_str, "");
};
function downloadObjectAsJson(str, filename) {
var data_str =
"data:text/json;charset=utf-8," + encodeURIComponent(str);
var anchor = document.createElement("a");
anchor.setAttribute("href", data_str);
anchor.setAttribute("download", filename + ".json");
}
});
If you only need the key, then an array of values, this will work better for you:
readXlsxFile(input.files[0]).then(function (data) {
let exportData = [];
for (i = 1; i < data.length; i++) {
exportData.push(data[i].toString());
}
document.getElementById("json-data").value = JSON.stringify({
imei: exportData,
});
});

How to check if a tag has image in it using Vanilla Javascript?

var squares = document.querySelectorAll('td');
var img1 = document.createElement("img");
img1.src = "Group 1.svg";
var img2 = document.createElement('img');
img2.src = "Ellipse 1.svg";
function changeMarker() {
if (this.textContent == '') {
this.appendChild(img1);
} else if (childElements[this].localName != null) {
this.appendChild(img2);
} else {
this.textContent = '';
}
}
for (var i = 0; i < squares.length; i++) {
squares[i].childNode.addEventListener('click', changeMarker);
}
The method .getElementsByTagName is available for you to use. Since we get the container first then call that element's copy of this method, we just look inside it and ignore the rest of the document.
<!doctype html>
<html>
<head>
<script>
"use strict";
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onLoaded, false);
function onLoaded(evt)
{
let d1 = byId('div1');
let d2 = byId('div2');
let imgCount1 = d1.getElementsByTagName('img').length;
let imgCount2 = d2.getElementsByTagName('img').length;
d1.textContent += ` - Img Count: ${imgCount1}`;
d2.textContent += ` - Img Count: ${imgCount2}`;
}
</script>
</head>
<body>
<div id='div1'>No image</div>
<div id='div2'>2 images<img><img></div>
<img><img><img>
</body>
</html>

HtmlService: google.script.run not recognizing gs function

I'm currently trying to pass an array of values from a Google Sheet to the HtmlService where I will have the user choose an option and eventually pass it back to the .gs script. I have been using these two links as references:
1. Google Documentation
2. Stack Overflow example
When running the code, I looked at my console and noticed this error:
VM3051:4 Uncaught TypeError: google.script.run.withSuccessHandler(...).getVersionArray is not a function
It appears that getVersionArray() is not being passed correctly. When removing this function from the rest of that google.script.run call, the error goes away.
Also, per link two, I tried that code with the template and never even got a window to pop up, so I have been using the HtmlOutput example from the Google documentation link as a starting point. I have also tried the code with and without the SandboxMode declaration.
gs code:
function bugPieChart() {
getVersionArray();
openDialog();
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}
}
index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run.withSuccessHandler(buildOptionsList)
.getVersionArray();
});
function buildOptionsList(uniqueArray) {
var list = $('#optionList');
list.empty();
for (var i = 0; i < uniqueArray.length; i++) {
list.append('<option value="' + uniqueArray[i].toLowerCase() + '">' + uniqueArray[i] + '</option>');
}
}
</script>
</head>
<body>
<select id="optionList">
<option>Loading...</option>
</select>
<input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
I think your just missing a closing bracket on the function above it.
function bugPieChart() {
getVersionArray();
openDialog();
}
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}

how to combine two vars in javascript?

i am trying to create dynamic textboxes. The textbox should be created only if the previous textbox is non-empty. So far i have done this
<!DOCTYPE html>
<html>
<head>
<script>
var i=0;
function myFunction()
{
var box = document.createElement("input");
box.type = "text";
var str=box+i;
if(i==0)
{
document.body.appendChild(box);
}
else if(document.getElementById('str').value!=0)
{
document.body.appendChild(box);
}
i++;
}
</script>
</head>
<body>
<input type="button" id="button" onclick="myFunction()" value="Show box" />
</body>
</html>
but str is not recognised as element id. Any help will be appreciated.
var i = 0;
function myFunction() {
var lastInput = document.getElementById('box' + i);
if (!lastInput) {
// always put first input
document.body.appendChild(createInput(0));
} else if (lastInput.value != 0) {
// append another one only if previous input content is non-null
i++;
document.body.appendChild(createInput(i));
}
}
function createInput(i) {
var box = document.createElement("input");
box.type = 'text';
box.id = 'box' + i;
box.value = 0;
return box;
}
Your wrongs:
str = 'box' + i;
Forget to assign box.id = str
Use getElementById(str) instead of getElementById('str')

JavaScript closure issue on dynamic element creation in a loop

During the execution of the page, a string gets composed containing the code that would need to be executed as the handler for the click event. The string could look like:
var handler = '"myFunction1(12, 20);myOtherFunction();"';
OR
var handler = '"myFunction1(12, 20);"'
When I create the buttons dynamically, and try to attach the events in a loop, it gets attached to the last button only. I can sense a closure issue but what am I missing?
Here is the code.
var buttons = [],
arg1 = 12,
arg2 = 20;
var butt1 = { Text: 'Bye', onClick: "anotherFunction();" },
butt = { Text: 'Hello', onClick: "myNewFunction();" },
butt2 = { Text: 'Bye333' };
buttons.push(butt1);
buttons.push(butt);
buttons.push(butt2);
function myNewFunction() {
alert('my New Function');
};
function myCloseFunction(arg1, arg2) {
alert('close: ' + arg1 + ' other: ' + arg2)
}
function anotherFunction() {
alert('Say Goodbye');
}
window.onload = function () {
var buttonContainer = document.getElementById('controlDiv'),
closeOnClick = "myCloseFunction(" + arg1 + ", " + arg2 + ")",
button;
for (var i = 0; i < buttons.length; i++) {
buttons[i].onClick = (buttons[i].onClick == null) ? closeOnClick : (closeOnClick + ';\n' + buttons[i].onClick);
button = document.createElement("INPUT");
button.type = 'button';
button.onclick = new Function(buttons[i].onClick);
if (i > 0)
buttonContainer.innerHTML += '&nbsp';
buttonContainer.appendChild(button);
}
};
The HTML page is simple:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<script src="Script.js" type="text/javascript"></script>
</head>
<body>
<h1>hello</h1>
<div id="controlDiv"></div>
</body>
</html>
Sensing a closure issue I have tried various options to close over any variables but was not successful. e.g.
button.onclick = (function (action, i) {
var name1 = 'hello' + i,
a123 = new Function('action', 'return function ' + name1 + '(){action();}')(action);
return a123;
} (new Function(buttons[i].onClick), i));
buttonContainer.innerHTML += '&nbsp'; - This line (or rather re-setting the innerHTML) is the problem. I don't think that the innerHTML property contains any events. Works as expected here.
I'd do it like this:
var buttons = [],
container = document.getElementById('controlDiv');
buttons.push(new Button('Bye', 'anotherFunction()'));
function Button(text, clickEvent){
var obj = document.createElement('input'),
self = this;
this.text = text;
this.clickEvent = clickEvent;
obj.type = 'button';
container.appendChild(obj);
obj.addEventListener('click', handleClick);
function handleClick(e){
if(self.clickEvent){
closeOnClick();
window[self.clickEvent];
} else {
closeOnClick();
}
};
}

Categories

Resources