Below is the entirety of the javascript code in question
This code works on desktop, however on an android device, it fails to colour the table element green
Presumably the listeners are what's broken but I do not have extensive debugging on the particular android device, the input device is a scanner, something which I also have for my desktop.
<script>
// document.getElementById("title").setAttribute("innerHTML", "")
let text = ""
document.addEventListener('keydown', (event) => {
if (event.key != 'Enter') {
var name = event.key;
var code = event.code;
text += event.key
}
}, false);
document.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
console.log(text)
//myFunction(1);
TableIt(text);
text = ""
}
})
function myFunction(string) {
document.getElementById(string).setAttribute("bgcolor","#dee")
}
function TableIt(text) {
var table = document.getElementById("VareTable");
for (var i = 0, row; row = table.rows[i]; i++) {
//rows would be accessed using the "row" variable assigned in the for loop
for (var j = 0, col; col = row.cells[j]; j++) {
if (col.innerHTML === text) {
myFunction(i-1);
}
//columns would be accessed using the "col" variable assigned in the for loop
}
}
}
</script>
Tried to do eventlistener('input', (event) => { . . . .
but to no success
Edit;
here is the full html above the JS
#page
#model WebStore.Pages.VareModel
#{
}
<br />
<h2 id="title">#(Model.Loc.Location)</h2>
<table class="table" id="VareTable">
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Description</th>
<th>EanNum</th>
</tr>
</thead>
<tbody>
#foreach (var Info in Model.listItems)
{
<tr id="#Info.ItemID">
<td>#Info.Item</td>
<td>#Info.Qty</td>
<td>#Info.Description</td>
<td id="#Info.ItemID ean">#Info.EAN</td>
</tr>
}
</tbody>
</table>
Given the difficulty of reliably getting the character on keydown on Android browsers and the complexity of building up a string from keydown events, I'd abandon that approach entirely. It looks like you want to collect a sequence of characters and then act on them when an Enter is received. That's exactly what a form with a single text input will do.
const table = document.getElementById("VareTable");
const input = document.getElementById("the-input");
const form = document.getElementById("the-form");
input.focus();
form.addEventListener("submit", (event) => {
// Don't actually submit the form
event.preventDefault();
// Get the text, clear it for next time
const text = input.value;
input.value = "";
// Refocus just in case
input.focus();
// Process this text
process(text);
});
function process(text) {
// This looks through all cells in the table and toggles
// a class on them depending on whether they match the
// text. You can adapt it to work by rows instead if you
// like.
for (const col of table.querySelectorAll("td")) {
const match = col.textContent === text;
col.classList.toggle("highlight", match);
}
}
.highlight {
background-color: #dee;
}
<form id="the-form">
<input type="text" id="the-input">
</form>
<table id="VareTable">
<tbody>
<tr>
<td>a</td>
</tr>
<tr>
<td>ab</td>
</tr>
<tr>
<td>abc</td>
</tr>
</tbody>
</table>
That works just fine on my Android tablet. You might be able to hide the input, but doing so may make it impossible to focus, which would probably break it.
Related
I am trying to make a data table from user input. i found out this solution that i am making objects from user input and pushing them to an array. after that, I am doing a for loop to make td. but somehow those datas are re writing in the same raw. and previous raw datas are getiing replaced by new input datas.what I am doing wrong here and every time I am refreshing the page the array is getting empty how to prevent this help me out tnx.
const form = document.getElementById("form");
const tdbody = document.getElementById("data");
const carDatas = [];
let count = 0;
class Car {
constructor(plate, carMaker, carModel, carOwner, carPrice, carColor) {
(this.plate = plate),
(this.carMaker = carMaker),
(this.carModel = carModel),
(this.carOwner = carOwner),
(this.carPrice = carPrice),
(this.carColor = carColor);
}
}
form.addEventListener("submit", (e) => {
const plate = document.getElementById("plate").value;
const carMaker = document.getElementById("carMaker").value;
const carModel = document.getElementById("carModel").value;
const carOwner = document.getElementById("carOwner").value;
const carPrice = document.getElementById("carPrice").value;
const carColor = document.getElementById("carColor").value;
const carDetails = new Car(
plate,
carMaker,
carModel,
carOwner,
carPrice,
carColor
);
carDatas.push(carDetails);
for (let i = 0; i < carDatas.length; i++) {
document.getElementById("data").innerHTML = document.createElement(
"tr"
).innerHTML = `<td>${carDatas[i].plate} </td>
<td>${carDatas[i].carMaker} </td>
<td>${carDatas[i].carModel} </td>
<td>${carDatas[i].carOwner} </td>
<td>${carDatas[i].carPrice} </td>
<td>${carDatas[i].carColor} </td> `;
}
e.preventDefault();
});
here is my html for table
<div class="database">
<h1>Cars Database</h1>
<table>
<thead>
<tr>
<th>LICENCE</th>
<th>MAKER</th>
<th>MODEL</th>
<th>OWNER</th>
<th>PRICE</th>
<th>COLOR</th>
</tr>
</thead>
<tbody id="data"></tbody>
</table>
</div>
Your for loop is bad!
I don't know if this part of your code is working, but if you have an array of objects you should see a function for arrays that is called map
arr.map((object) => {
return <td>{object.plate}</td>
})
this function is example, try to look for documentation
I am building an automated solution on Google Apps Scripts for my job that is testing my basic knowledge of HTML and JS. I would appreciate some guidance.
Context:
I am building a tool to automate certain tasks on Google Sheets through formulas and scripts
The task I'm having issues with begins with the user clicking on a button that opens a getUi() Modal Dialog
The main challenge is to extract data out of an HTLM table where the user makes inputs
JS code triggering the popup (just for context):
function openbrief() {
//pull necessary values
var supp_main = SpreadsheetApp.getActive().getSheetByName('supp_main')
//projects
var projrng = supp_main.getRange(2, 64, 1000);
var projval = projrng.getValues();
var projname = projval.filter(String)
//content_category
var catrng = supp_main.getRange(2, 65, 1000);
var catval = catrng.getValues();
var catname = catval.filter(String)
//content_type
var typerng = supp_main.getRange(2, 66, 1000);
var typeval = typerng.getValues();
var typename = typeval.filter(String)
//format
var formatrng = supp_main.getRange(2, 67, 1000);
var formatval = formatrng.getValues();
var formatname = formatval.filter(String)
//channel
var chanrng = supp_main.getRange(2, 68, 1000);
var chanval = chanrng.getValues();
var channame = chanval.filter(String)
var widget = HtmlService.createTemplateFromFile('briefs');
widget.projdata = projname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.catdata = catname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.typedata = typename.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.formatdata = formatname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
widget.chandata = channame.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
SpreadsheetApp.getUi().showModalDialog(widget.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(5000).setWidth(5000), 'Briefs');
}
Questions:
I have a GS/JS script within the HTML that is supposed to run through the table values, push them to an array and paste them to a gSheet. However it does not do that. I'm not experience with for loops and arrays on JS, and I can't tell what's not working.
Will this type of script pull the values from the dropdown menus? I suspect it won't as they seem to be sitting on top of the cell. But I'm unsure (see screenshot for more context)
Any other improvements or suggestions based on both code or screenshot is very welcome
References:
The script is "inspired" by this: Getting value from table cell in JavaScript...not jQuery
Here's another case I've been browsing but I fail to understand the solution provided: extract value from dynamic html table
HTML code
<table id="brief_table">
<thead>
<tr>
<th>Content category</th>
<th>Description</th>
<th>Content type</th>
<th>Format</th>
<th>Channel</th>
<th>Assets</th>
<th>Start date</th>
<th>End date</th>
<th>Relevant links</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select id="catname" style="Border: none;"><?!= catdata ?></select>
</td>
<td contenteditable='true'>Test</td>
<td>
<select id="typename" style="Border: none;"><?!= typedata ?></select>
</td>
<td>
<select id="formatname" style="Border: none;"><?!= formatdata ?></select>
</td>
<td>
<select id="channame" style="Border: none;"><?!= chandata ?></select>
</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
<td contenteditable='true'>Test</td>
</tr>
</tbody>
</table>
<script>
function pasteBrief() {
var table = document.getElementById("brief_table");
var tablevalues = [];
for (var r = 0, n = table.rows.length; r < n; r++) {
for (var c = 0, m = table.rows[r].cells.length; c < m; c++) {
tablevalues.push(table.rows[r].cells[c].innerHTML);
}
}
alert(tablevalues);
google.script.run.pasteBriefVal(tablevalues);
}
</script>
GS SERVER CODE
function pasteBriefVal(tablevalues){
SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1:cb').setValues(tablevalues);
}
Screenshots:
Additional info:
I have managed to stringify the array, which in return allow me to paste it as a value in one single cell. This enable me to take a closer look to it (see img below)
Link to copy of the spreadsheet: link - to trigger the popup "briefs.html" you want to go to "[SOW] #2-Project & deliverables" and click on the icon that says "PLAN" around D24
Edits:
Moved setValues out of HTML file back to GS side. Called the new GS function out from HTML via google.script.run.pasteBriefVal(tablevalues)
Added more information on what the array look like
Added the link to a copy of the original spreadsheet should anyone want to take a deeper look
Server side GS and Client side JS
The below server side code does not run in a browser:
SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1').setValues(tablevalues);
If you wish to run server side code the use google.script.run
first I'm sorry if at some point I express myself badly, English is not my native language. I am developing an application in which the user sends 2 values through a form and in another page I use one of those data (string with comma separated options) to show a specific table and hide the others, and with the second data (Integer) I show one of the rows of that table.
What I already have:
I have the form and send the data through the Query String, I capture that data, I assign a variable to the integer and to the text string I separate it by commas and create an array.
URL Example: app.tables.example/?id=123&ops=option1%2c+option2
//Read parameters sent by form
const param = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop)
});
//Assign integer to a variable
let num = param.id;
//Assign options to a variable
let op = param.ops;
//Separate string with commas
let opsplit = op.split(',');
Up to here everything is perfect, I can print all the variables without any problem, now I need to compare the array with the id of each table, show the one that corresponds and hide the others. (The id of the tables is the same that user passes with the text string).
The tables look something like this:
<div id="option1" class="table-1">
<table width="100%">
<thead>
<tr>
<th align="left">Option1</th>
<th align="left">Integer</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Number</td>
<td align="left">Info</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">textblock</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">textblock</td>
</tr>
</tbody>
</table>
</div>
//As you can see the id of each table corresponds to what the user chose
<div id="option2" class="table-1">
<table width="100%">
<thead>
<tr>
<th align="left">Option2</th>
<th align="left">Integer</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Number</td>
<td align="left">Info</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">textblock</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">textblock</td>
</tr>
</tbody>
</table>
</div>
The problem:
I'm supposed to use the array elements in a "for" loop and compare them with the id of each table, then show that table and hide others, but I don't know exactly how to do it.
function myFunction() {
var input, filter, table, tr, td, i, y, txtValue;
for (r = 0; r<opsplit.length; r++){
input = opsplit[r];
filter = function(x){
return x.toUpperCase();
};
opsplit = opsplit.map(filter);
}
//When I test this, it does not return any value,
//innerHTML error
for(y = 0; y<opsplit.length; y++){
table = document.getElementById(opsplit[y]).innerHTML;
//I use this section to test, it should show me the row,
//but since the previous loop failed, it does nothing.
// What I really need is to show the whole
// table where this data is located and hide the other tables.
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
}
myFunction();
I am really stuck at the moment and would appreciate any help. What is the correct way to use the string array, and how can I hide the tables that the user does not need?
Ok, thanks to those who took the time to write a comment, but I found the solution, I had to convert the form data to a string and an integer. Then I was able to compare that string to the classes id. I am writing the answer in case anyone finds it useful.
//Read parameters sent by form
const param = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop)
});
//Assign number to a variable
let num = param.id;
//Convert to integer
let numint = parseInt(num);
//Assign options to a variable
let op = param.ops;
//Convert to String
let opstr = op.string();
//Separate string with commas
let opsplitstr = opstr.split(',');
//Assign class to a variable
tableclass = document.getElementsByClassName('table-1');
//Compare table class ids with string array
if (opsplitstr[0] == tableclass[0].id{
}
//We need a loop if we need compare all elements
TLDR: The URL does not send information about the data type, so I had to read it and convert it according to my need.
I have a table where one td gets 1 if a checkbox is checked and I would like to multiple this td with another and display it in a third one.
See the html here:
<div>
<input type="checkbox" id="fut1">check</input>
</div>
<table border="1" cellpadding="10" id="countit">
<tr>
<td id="td1"></td>
<td id="td2">5000</td>
<td id="td3"></td>
</tr>
</table>
And here is the js:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
});
$('#td1').change(function () {
var me = $('#td1').value;
var ar = $('#td2').value;
var sum = me * ar;
$('#td3').text(sum);
});
$('#td1').change(function () { // <--- td elements don't have a change event listener/handler
var me = $('#td1').value; // <--- td elements don't have a value
var ar = $('#td2').value; // <--- td elements don't have a value
var sum = me * ar;
$('#td3').text(sum);
});
If you want to do it this way:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
callTdChange();
});
function callTdChange() {
var me = parseInt($('#td1').text());
var ar = parseInt($('#td2').text());
var sum = me * ar;
$('#td3').text(sum);
}
Of course, the better way should be to use form elements (inputs) in the case you want to save your data to a server, or use change behaviors.
#td1 doesn't support the change event, because that's only meant for interactive elements (like input, select, or textarea).
You can either do the calculation in your first event listener in #fut1, or declare an input element inside #td1.
<body>
<input type="text" id="search"/>
<table id="boxdata">
<tr>
<td class="namebox1">jQuery</td>
</tr>
<tr>
<td class="namebox2">javascript</td>
</tr>
<tr>
<td class="namebox3">php</td>
</tr>
<tr>
<td class="namebox4">sql</td>
</tr>
<tr>
<td class="namebox5">XML</td>
</tr>
<tr>
<td class="namebox6">ASP</td>
</tr>
</table>
</body>
<script>
$(document).ready(function(){
$('#search').keyup(function(){
searchBox($(this).val());
});
});
function searchBox(inputVal) {
$('#boxdata').find('tr').each(function(index, row){
var names = $(row).find('td');
var found = false;
if(names.length > 0) {
names.each(function(index, td) {
var regExp = new RegExp(inputVal, 'i');
if(regExp.test($(td).text()) & inputVal != ''){
found = true;
return false;
}
});
if(found == true)
$(row).addClass("red");
else
$(row).removeClass("red");
}
});
}
</script>
there's a textfield for searching words and there are 6 words in the each 6 boxes below textfield.(I omitted css codes. but, it wouldnt matter to solve the problem.). if i type a letter 's' then the words that including letter 's' like 'javascript', 'sql', 'ASP' these font-color will be changed black to red. And i made it by using table elements in html but i'd like to change all elements into div style to put some data fluidly later. i have difficulty to fix especially jquery. how can i fix it?
You can simplify this a little bit.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal, 'i');
$('#boxdata').find('tr').removeClass('red').filter(function() {
return $(this).find('td').filter(function() {
return regExp.test( $(this).text() );
}).length && $.trim(inputVal).length;
}).addClass('red');
}
So remove the red class from all <tr>'s first, then filter them, test the text of each <td>, if it matches, return the <tr> and then add the class red again.
Here's a fiddle
As for changing from a table to div, the jQuery would depend on how you structure your markup, but the principle would remain the same.
Here's another fiddle
You can make javascript code HTML agnostic by using css classes instead of element names. Demo.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal = $.trim(inputVal), 'i'),
highlight = 'red';
$('#wrapper').find('.word') //instead of tr/td/div
.removeClass(highlight)
.each(function(){
var $this = $(this);
inputVal && regExp.test($this.text()) &&
$this.addClass(highlight);
});
}