I'm trying to complete a system with which a book shop can enter the a sample of 5 books that were sold that day along with their prices. These values would then be displayed to the page.
I have managed this and now wish to add the total price. I have tried all the methods mentioned on stack overflow and elsewhere to get the sume of the price array but I either get the last price entered or "NaN" when i try to get the total. Please help!!!
Here is my code
document.addEventListener("DOMContentLoaded", function() {
enterBooks()
}); // Event listener - When page loads, call enterBooks function
function enterBooks() { // enterBooks function
var books = []; // Defines books variable as an array
for (var i = 0; i < 5; i++) { // for loop to loop 5 times
books.push("<li>" + prompt("Enter a book") + "</li>"); // PUSH adds a new item to the array in the form of a prompt with <li> tags either side of each.
var price = []; // Defines price variable as an array
for (var p = 0; p < 1; p++) { // for loop to loop 1 time
price.push("<li>" + "£" + parseInt(prompt("Enter the price")) + "</li>"); // Once again PUSH adds a new item to the array in the form of a prompt with <li> tags either side of each. This then displays next to each book.
}
document.getElementById("displayPrice").innerHTML += (price.join(""));
document.getElementById("displayBooks").innerHTML = (books.join(""));
}
// --------- This is the part i cannot seem to get -----------
var total = 0;
for (var t = 0; t < price.length; t++) {
total = total + price[t];
}
document.getElementById("total").innerHTML = total;
}
ul {
list-style-type: decimal; /* Gives list items numbers */
font-size:25px;
width:20%;
}
#displayBooks {
float:left;
width:20%;
}
#displayPrice {
float:left;
width:50%;
list-style-type: none;
}
<!DOCTYPE html>
<html>
<head>
<title>Bookshop</title>
<link href="css/style.css" rel="stylesheet">
<!-- StyleSheet -->
</head>
<body class="text-center">
<h1>BookShop</h1>
<!-- Header -->
<h3>Books sold</h3>
<!-- Team intro -->
<ul id="displayBooks">
<!-- Div to display the teams -->
</ul>
<ul id="displayPrice">
<!-- Div to display the teams -->
</ul>
<div id="total">
</div>
<script src="js/script.js"></script>
</body>
</html>
P.S This is my first time asking a question on here so if it's not structured very well then I apologise in advance and hope you can still make it all out
try this:
document.addEventListener("DOMContentLoaded", function() {
enterBooks()
}); // Event listener - When page loads, call enterBooks function
function enterBooks() { // enterBooks function
var books = []; // Defines books variable as an array
var price = [];
var priceText=[];
for (var i = 0; i < 5; i++) { // for loop to loop 5 times
books.push("<li>" + prompt("Enter a book") + "</li>"); // PUSH adds a new item to the array in the form of a prompt with <li> tags either side of each.
price[i]=parseInt(prompt("Enter the price"));
priceText.push("<li>" + "£" + price[i] + "</li>"); // Once again PUSH adds a new item to the array in the form of a prompt with <li> tags either side of each. This then displays next to each book.
document.getElementById("displayPrice").innerHTML = priceText.join("");
document.getElementById("displayBooks").innerHTML = (books.join(""));
}
// --------- This is the part i cannot seem to get -----------
var total = 0;
for (var t = 0; t < price.length; t++) {
total = total + price[t];
}
document.getElementById("total").innerHTML = total+ "£";
}
ul {
list-style-type: decimal; /* Gives list items numbers */
font-size:25px;
width:20%;
}
#displayBooks {
float:left;
width:20%;
}
#displayPrice {
float:left;
width:50%;
list-style-type: none;
}
<!DOCTYPE html>
<html>
<head>
<title>Bookshop</title>
<link href="css/style.css" rel="stylesheet">
<!-- StyleSheet -->
</head>
<body class="text-center">
<h1>BookShop</h1>
<!-- Header -->
<h3>Books sold</h3>
<!-- Team intro -->
<ul id="displayBooks">
<!-- Div to display the teams -->
</ul>
<ul id="displayPrice">
<!-- Div to display the teams -->
</ul>
<div id="total">
</div>
<script src="js/script.js"></script>
</body>
</html>
It is because you are adding the entire HTML in the price array and hence it will not add as it is not numerical data.
This should work:
var input = parseInt(prompt("Enter the price"));
price.push(input);
please change
for (var p = 0; p < 1; p++) { // for loop to loop 1 time
price.push("<li>" + "£" + parseInt(prompt("Enter the price")) + "</li>"); // Once again PUSH adds a new item to the array in the form of a prompt with <li> tags either side of each. This then displays next to each book.
}
document.getElementById("displayPrice").innerHTML += (price.join(""));
to
// no need for loop
price.push(parseInt(prompt("Enter the price"), 10)); // just the price, added base to parseInt (really? not parseFloat?)
document.getElementById("displayPrice").innerHTML += price.map(function (a) {
return '<li>GBP' + a + '</li>'; // build here the string for output
}).join("");
Related
This is my first time posting here so please let me know if I need to edit anything.
I am working on a program that runs through data that is imported in google sheets, displays one "row" of data in an HTML web app where the user can then assign an account number (found in a dropdown list) to the item that is displayed, and move on to the next row in the data. Each item in the data has a ID number and based on this ID number and the description of the data, the user selects the appropriate account number in the list to assign to the data.
The problem is that there are hundreds of these account numbers and having the users scroll/search through these to find the correct account will be very tedious.
The good news is that only certain accounts can be assigned to an ID number. I can effectively sort the dropdown list to only show accounts that can be assigned to the current ID therefore making the user's job much easier and much quicker.
However, I have no idea how to update the dropdown after the item loads on the html page. I am able to get the current ID number and sort through the accounts, I just am not able to update the drop down.
I have pasted the code.gs and the html/javascript code.
I did not include all of the code in code.gs file as some of it has nothing to do with my problem.
I am using Materialize CSS.
Code.gs:
var url = "hidden";
var ss = SpreadsheetApp.openByUrl(url);
var masterWS = ss.getSheetByName("Master List");
var items = [];
var Route = {};
Route.path = function (route, callback){
Route[route] = callback;
}
function doGet(e) {
Route.path("summary", summaryPage);
Route.path("edit", editPage);
if(Route[e.parameters.v]){
return Route[e.parameters.v]();
} else {
return editPage();
}
}
function summaryPage(){
var tmp = HtmlService.createTemplateFromFile("summary");
var sumList = showSummary();
tmp.summaryList = sumList;
return tmp.evaluate();
}
function include(fileName){
return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}
function editPage(){
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("GLAccounts");
// Create drop down and populate with all account options
var SSassetList = ws.getRange(2,1, getLastRowSpecial("A", "GLAccounts"),1).getValues();
var htmlAssetList = SSassetList.map(function (r){return '<option>' + r[0] + '</option>';}).join('');
var tmp = HtmlService.createTemplateFromFile("page");
tmp.assetList = htmlAssetList;
return tmp.evaluate();
}
function calculateTotalEntries(){
//Logger.log("Done: " + done);
var lastRow = masterWS.getLastRow();
var totalEntries = 0;
var i = lastRow;
while (masterWS.getRange(i, 1).getValue() != "Transaction Date"){
i--;
totalEntries++;
}
masterWS.getRange("R1").setValue(totalEntries);
masterWS.getRange("R2").setValue(lastRow);
}
function userClicked(userInfo){
var r = masterWS.getRange("P1").getValue();
var GLAccount = userInfo.act;
var lastRow = masterWS.getRange("R2").getValue();
var totalEntries = masterWS.getRange("R1").getValue();
if(!(masterWS.getRange("P3").getValue())){
//Logger.log("Done parsing. Items length: " + items.length);
if(r <= totalEntries - 1 ){
masterWS.getRange("P4").setValue(lastRow - totalEntries + 1 + r);
if(masterWS.getRange("P1").getValue() != 0){
masterWS.getRange(lastRow - totalEntries + r, 8).setValue(GLAccount);
}
r = r + 1;
masterWS.getRange("P1").setValue(r);
} else {
//Logger.log("Last one");
masterWS.getRange("P3").setValue(true);
masterWS.getRange(lastRow, 8).setValue(GLAccount);
//return Error;
resetCounters();
calculateChange();
}
}
}
function showItem(){
var row = masterWS.getRange("P4").getValue();
return "Item: " + masterWS.getRange(row,5).getValue() + "; Date: " + slice(masterWS.getRange(row,1).getValue(), 13) + "; ID: "+ masterWS.getRange(row,6).getValue();
}
function getData(){
var row = masterWS.getRange("P4").getValue();
var id = "";
id = masterWS.getRange(row,6).getValue().toString();
var availAccounts = [];
var IDSheet = ss.getSheetByName("MerchantCodes");
var lastIDRow = IDSheet.getLastRow();
var lastIDCol = 0;
var currentRow = 0;
for(var i = 6; i < lastIDRow; i++){
if(IDSheet.getRange(i, 1).getValue().toString() == id){
currentRow = i;
break;
}
}
//Logger.log("ID: " + id + " # row " + i);
for( var j = 1; j < 10; j++){
if(IDSheet.getRange(currentRow,j).getValue() != ""){
lastIDCol = j;
}
}
//Logger.log("Last Column for row " + i + ": " + lastIDCol);
for(var r = lastIDCol - (lastIDCol - 3) + 1; r < lastIDCol+1; r++){
//Logger.log("Account: " + IDSheet.getRange(currentRow,r).getValue());
availAccounts.push(IDSheet.getRange(currentRow,r).getValue());
}
return availAccounts;
}
function resetCounters(){
masterWS.getRange("P1").setValue(0);
masterWS.getRange("P3").setValue(false);
masterWS.getRange("P4").setValue("");
masterWS.getRange("P5").setValue("");
masterWS.getRange("P6").setValue("");
}
function getLastRowSpecial(col, sheetName){
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName(sheetName);
var data = ws.getRange(col + "2:" + col).getValues();
var lastRowData = data.filter(String).length;
return lastRowData;
}
}
HTML:
The item that is displayed in the web app, which changes based on the data, is in the tags.
The dropdown list is populated using the tags. The data in those tags comes from the doGet()and editPage() functions in the code.gs file.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<?!= include("page-css"); ?>
</head>
<body>
<div class = "container"> <!-- Open container -->
<div> <!-- Open row -->
<label>Item</label>
<p><span id="current"></span></p>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="btn2" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Start</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<div class="input-field col s6">
<select id="glAcc">
<option disabled selected>Choose your GL Account</option>
<?!= assetList; ?>
</select>
<label>GL Account</label>
</div>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="updDrop" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Update Dropdown
<i class="material-icons right">send</i>
</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="btn" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<a href="<?= ScriptApp.getService().getUrl(); ?>?v=summary" id="summary" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Go to Summary Page
<i class="material-icons right">arrow_forward</i>
</a>
</div> <!-- Close row -->
</div> <!-- Close container -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<?!= include("page-js"); ?>
</body>
</html>
HTML JS Code:
<script>
document.addEventListener('DOMContentLoaded', function(){
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
document.addEventListener('DOMContentLoaded', reset);
document.getElementById("btn").addEventListener("click",doStuff);
document.getElementById("btn2").addEventListener("click",doStuff);
document.getElementById("sumBtn").addEventListener("click", summary);
document.getElementById("updDrop").addEventListener("click", updateDropdown);
function doStuff(){
var userInfo = {};
userInfo.act = document.getElementById("glAcc").value;
google.script.run.withSuccessHandler(findItem).userClicked(userInfo);
//findItem();
//google.script.run.getLength();
// Reset dropdown
var myApp = document.getElementById("glAcc");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
}
function reset(){
google.script.run.resetCounters();
google.script.run.calculateTotalEntries();
document.getElementById("current").textContent = "Click the Start Button";
}
function updateDropdown(){
google.script.run.withSuccessHandler(updateSelect).getData();
}
function updateSelect(vA){
var select = document.getElementById("glAcc");
select.options.length = 0;
vA.unshift("");
for(var i = 1; i < vA.length; i++){
select.options[i] = new Option(vA[i], vA[i]);
}
}
function findItem(){
google.script.run.withSuccessHandler(changeItem).showItem();
}
function changeItem(item){
document.getElementById("current").textContent = item;
//document.getElementById("options"). = "<option>1</option><option>2</option>";
}
function summary(){
google.script.run.withSuccessHandler(findSummary).calculateChange();
}
function findSummary(){
google.script.run.withSuccessHandler(changeSummary).showSummary();
}
function changeSummary(summary){
document.getElementById("sumText").textContent = summary;
}
</script>
Basically to summarize, I want the dropdown options to update as the item displayed also updates. If it is not possible to update at the same time, I can add a button which will update the dropdown once clicked.
I do not want to share the whole code/spreadsheet to everyone, but if you want access please message me and I can share it to you.
Thank you.
welcome to the SO community.
I believe the problem is not in the Apps Script.
When you use Materialize Select you need to re-init it.
This is the function I found in my codebase, it should help you:
function fillMaterializeSelect(elSelect, data) {
elSelect.options.length = 0;
for (let i = 0; i < data.length; i++) {
const dataElement = data[i];
const option = document.createElement("option");
option.value = dataElement.value;
option.text = dataElement.text;
elSelect.add(option);
}
M.FormSelect.init(elSelect);
}
Here is a JavaScript function I use a lot for updating <select>.
function updateSelect(vA,id){
var id=id || 'sel1';
var select = document.getElementById(id);
select.options.length = 0;
vA.unshift("");
for(var i=1;i<vA.length;i++)
{
select.options[i] = new Option(vA[i],vA[i]);//one is the value and the other is the display value
}
}
You retrieve the data with a
gooogle.script.run
.withSuccessHandler(updateSelect)
.getData();
I am looking to add an array to a div. Not working with document.getElementsByClassName('boxed').innerHTML = numList. I am able to write the array to the DOM with document.write(numList).
Here's the whole HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title>Super Lotto</title>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Libre+Franklin" rel="stylesheet">
<link href="lotto-styles.css" rel="stylesheet">
<script>
do {
var high = prompt('What\'s the highest number you want to generate','');
high = parseInt(high, 10);
} while (isNaN(high));
do {
var nums = prompt('How many numbers do you want to generate','');
nums = parseInt(nums, 10);
} while (isNaN(nums));
function rand(highestNum) {
var randomNumber =
Math.floor(Math.random() * highestNum) + 1;
return randomNumber;
}
var numList = [];
for (var i = 0; i < nums; i++) {
// Go through this loop quantity of times
numList.unshift(rand(high));
// add new number to end of array
};
numList.toString();
document.getElementsByClassName('boxed').innerHTML = numList;
</script>
</head>
<body>
<div id="container">
<header>
<h1>Lucky Numbers</h1>
</header>
<main>
<div class="boxed"></div>
<p>Good luck!</p>
</main>
</div> <!-- Closing container -->
</body>
</html>
your problem is that in innerHTML you can't add an array, just a string, to add the numbers you need to do something like numList.join(" ");, I modified your code to do that. another thing I change is that instead of use "boxed" as a class, I use it as an id because getElementsByClassName return an nodeList.
do {
var high = prompt('What\'s the highest number you want to generate','');
high = parseInt(high, 10);
} while (isNaN(high));
do {
var nums = prompt('How many numbers do you want to generate','');
nums = parseInt(nums, 10);
} while (isNaN(nums));
function rand(highestNum) {
var randomNumber =
Math.floor(Math.random() * highestNum) + 1;
return randomNumber;
}
var numList = [];
for (var i = 0; i < nums; i++) {
// Go through this loop quantity of times
numList.unshift(rand(high));
// add new number to end of array
};
numList.toString();
document.getElementById('boxed').innerHTML = numList.join(" ");
<div id="container">
<header>
<h1>Lucky Numbers</h1>
</header>
<main>
<div id="boxed"></div>
<p>Good luck!</p>
</main>
</div>
When you get elements by class names (source: https://developer.mozilla.org/fr/docs/Web/API/Document/getElementsByClassName), you receive an array,so you have to precise which element of the array you want, I think [0] in your case.
It's better to work with an ID if you only have one place to put the result, like this:
do {
var high = prompt('What\'s the highest number you want to generate','');
high = parseInt(high, 10);
} while (isNaN(high));
do {
var nums = prompt('How many numbers do you want to generate','');
nums = parseInt(nums, 10);
} while (isNaN(nums));
function rand(highestNum) {
var randomNumber =
Math.floor(Math.random() * highestNum) + 1;
return randomNumber;
}
var numList = [];
for (var i = 0; i < nums; i++) {
// Go through this loop quantity of times
numList.unshift(rand(high));
// add new number to end of array
console.log(numList)
};
numList.toString();
document.getElementById('boxed').innerHTML = numList;
<!DOCTYPE html>
<html lang="en">
<head>
<title>Super Lotto</title>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Libre+Franklin" rel="stylesheet">
<link href="lotto-styles.css" rel="stylesheet">
</head>
<body>
<div id="container">
<header>
<h1>Lucky Numbers</h1>
</header>
<main>
<div id="boxed"></div>
<p>Good luck!</p>
</main>
</div> <!-- Closing container -->
</body>
</html>
I have to display a text field and a button “Generate times table”. When the user enters an integer from 1 to 9 and clicks the button, two duplicate times tables will appear side-by-side. However, the times tables on the right needs to be presented in an unordered list style.
When the user enters another number and click the button, the old times tables disappear and the new times tables will be generated accordingly.
I have managed to display one times tables set, however the second version (unordered list) won't display adjacent to it.
<html>
<head>
</head>
<body>
Enter integer:<input onClick="stopCounterAnimation()" id="number"
type="text">
<button onclick="startCounterAnimation()">Start Animation</button>
<button onclick="stopCounterAnimation()">Stop Animation</button>
<br/><br/>
<span id="counter"></span>
<script>
var counter = 0;
var counterSchedule;
var input = document.getElementById("number");
var counterSpan = document.getElementById("counter");
function startCounterAnimation() {
counterSchedule = setInterval(showCounter, 1000);
}
function showCounter() {
if (~~input.value) {
if (counter >= 9)
counter = 0;
counter++;
counterSpan.innerHTML = input.value + " X " + counter + " = "
+ eval(input.value + " * " + counter);
}
}
function stopCounterAnimation() {
clearInterval(counterSchedule);
input.value = "";
counter = 0;
}
</script>
</body>
</html>
Hi there!
I am a beginner both in JavaScript and in Google Sheets, but I am trying to find a way for Google Apps Script to basically scan the data I have brought in there from a Swedish Online Bank where they have some information about how the stocks go up and down.
Furthermore, I want to be notified by email when one of these on my list goes down by for example 5 % in a day.
I tried something like this:
let arrayRow = ["+" + 5.91 + "%", "+" + 5.22 + "%", "-" + 5.5 + "%"];
console.log(arrayRow);
function stockPricePlus() {
if (arrayRow >= "+" + 5 + "%") {
console.log("Yay! One of your stocks are going up by 5 % or more!");
}
}
function stockPriceMinus() {
if (arrayRow <= "-" + 5 + "%") {
console.log("Oh noes! One of your stocks are going down by 5 % or more!");
}
}
stockPricePlus();
stockPriceMinus();
And this works in my JavaScript file, but I am not quite sure how to make it pull the data continuously from the Google Sheets and run through them like a loop?
I found something on the internet that seemed to kind of do the job, but I also see that there are some missing parts in the code.
function sendEmails () {
var sheet = SpreadsheetApp.getActiveSheet();
var Price = sheet.getRange("B34:B").getValues();
var data = Price.getValues();
var results = [];
for (var i = 0; i < data.length; ++i) {
var row = data[i];
Logger.log(Price);
if (Price >= "+" + 5 + "%") {
MailApp.sendEmail("johnsmith#gmail.com", "Stock Price Alert from Stock Price Google Script", "One of your stocks are going up by 5 % or more!");
}
if (Price <= "-" + 5 + "%") {
MailApp.sendEmail("johnsmith#gmail.com", "Stock Price Alert from Stock Price Google Script", "One of your stocks are going down by 5 % or more!");
}
A ClientSide Timer for Collecting Periodic Stock Prices using GoogleFinance cell formulas
This code is a portion of code that I have used to check stocks. It has a timer function which runs clientside on your browser and you can adjust the sampling rate as you desire. I'd recommend no less that once every 5 minutes. That gives a good long time to get everything done. I also added a checkStats function which calculates percent change using the formula (max-min/max) * 100 and it compares this value with a value that you can set for each stock on the StockPrices page. It is also set up to send emails if the percent change is greater than a threshold and you can set. You can have as many stocks as you wish but you may need to adjust the sample rate if you try to get too many. You will have to add the email recipient address.
I have several other functions which chart the various stocks in different ways that I didn't include in this. I tried to keep this simple so I wouldn't be surprised if I have inadvently left some things out. Please note this script does not start automatically each day. In fact I hardly ever use it but I thought it would be an interesting thing to do and since then I've found the timer portion to be quite handy.
It's been my experience that GoogleFinance tags do not refresh regularly throughout the day. I've seen them not change at all for as long as 12 minutes while watching the stock prices change on another more elaborate system that runs on a personal computer.
datatimer.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<style>
#my_block{border:2px solid black;background-color:rgba(0,150,255,0.2);padding:10px 10px 10px 10px;}
#conv_block{border: 1px solid black;padding:10px 10px 10px 10px;}
.bttn_block{padding:5px 5px 0px 0px;}
.sndr_block {border:1px solid rgba(0,150,0,0.5);background-color:rgba(150,150,0,0.2);margin-bottom:2px;}
</style>
</head>
<body>
<form>
<div id="my_block" class="block form-group">
<div class="sndr_block">
<div id="myClock" style="font-size:20px;font-weight:bold;"></div>
<br />Timer Duration(minutes):
<br /><input id="txt1" type="text" size="4" class="action"/>
<select id="sel1" onChange="loadTxt('sel1','txt1');">
</select>
<div id="cntdiv"></div>
<br /><strong>Timer Controls</strong>
<div class="bttn_block"><input type="button" value="Start" name="startShow" id="startShow" onClick="startmytimer();changeData();" class="red" /></div>
<div class="bttn_block"><input type="button" value="Stop" name="stopTimer" id="stopTimer" class="red" /></div>
<div class="bttn_block"><input type="button" value="Single Ping" name="changedata" id="chgData" class="red" onClick="changeData();" /></div>
</div>
<div id="btn-bar">
<br /><input type="button" value="Exit" onClick="google.script.host.close();" class="green" />
</div>
</div>
</form>
<script>
var idx=1;
var myInterval='';
var cnt=0;
$(function() {
var select = document.getElementById('sel1');
select.options.length = 0;
for(var i=1;i<61;i++)
{
select.options[i-1] = new Option(i,i * 60000);
}
select.selectedIndex=4;
$('#startTimer').click(startmytimer);
$('#stopTimer').click(stopTimer);
$('#txt1').val(String(select.options[select.selectedIndex].value));
startTime();
});
function startTime(){
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('myClock').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
}
function checkTime(i){
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
function startmytimer(){
document.getElementById('cntdiv').innerHTML='<strong>Timer Started:</strong> ' + document.getElementById('myClock').innerHTML;
myInterval=setInterval(changeData, Number($('#txt1').val()));
}
function stopTimer(){
document.getElementById('cntdiv').innerHTML='Timer Stopped';
clearInterval(myInterval);
}
function loadTxt(from,to){
document.getElementById(to).value = document.getElementById(from).value;
}
function changeData(){
$('#txt1').css('background','#ffffcc');
google.script.run
.withSuccessHandler(updateDisplay)
.changeData();
}
function updateDisplay(t){
$('#txt1').css('background','#ffffff');
document.getElementById('cntdiv').innerHTML='<strong>Timer Running:</strong> Count= ' + ++cnt + ' <strong>Time:</strong> ' + t;
}
console.log('My Code');
</script>
</body>
</html>
Code.gs:
function onOpen(){
SpreadsheetApp.getUi().createMenu('MyTools')
.addItem('Show Timer SideBar', 'showTimerSideBar')
.addToUi();
}
//This is the function driven by the clientside timer trigger It also creates new data sheets for each day.
function changeData(){
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('StockPrices');
var rg=sh.getRange(3,1,1,sh.getLastColumn());
var vA=rg.getValues();
var n=new Date();
var tmr=Utilities.formatDate(n, Session.getScriptTimeZone(), "HH:mm:ss");
var ts=Utilities.formatDate(n, Session.getScriptTimeZone(), "E-MMddyy-HHmmss");
var sheetTitle=Utilities.formatDate(n, Session.getScriptTimeZone(), "E-MMddyy");
vA[0][0]=ts;
if(isSheet(sheetTitle)){
ss.getSheetByName(sheetTitle).appendRow(vA[0]);
}else{
var sht=ss.insertSheet(sheetTitle);
var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues();
hA[0][0]="TimeStamp";
sht.appendRow(hA[0]);
sht.appendRow(vA[0]);
}
checkStats(sheetTitle);
return tmr;
}
function showTimerSideBar()
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('StockPrices');
sh.getRange(5,2,1,sh.getLastColumn()-1).clearContent();//clears the sent row
var ui=HtmlService.createHtmlOutputFromFile('datatimer').setTitle('Javascript Trigger Generator');
SpreadsheetApp.getUi().showSidebar(ui);
}
function isSheet(sheetname){
var r=false;
var ss=SpreadsheetApp.getActive();
var allSheets=ss.getSheets();
for(var i=0;i<allSheets.length;i++){
if(allSheets[i].getName()==sheetname){
r=true;
break;
}
}
return r;
}
//This function checks stats and compares them to limits to determine if warning email messages should be sent
function checkStats(page) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(page);
var rg=sh.getRange(1,2,sh.getLastRow(),sh.getLastColumn()-1);
var vA=rg.getValues();
var minA=vA[1].slice(0);
var maxA=vA[1].slice(0);
var pchA=[];
for(var i=2;i<vA.length;i++) {
for(var j=0;j<vA[i].length;j++) {
if(vA[i][j]>maxA[j]) {
maxA[j]=vA[i][j];
}
if(vA[i][j]<minA[j]) {
minA[j]=vA[i][j];
}
}
}
for(var i=0;i<minA.length;i++) {
pchA.push(Number(((maxA[i]-minA[i])/maxA[i]) * 100).toFixed(2));
}
var spsh=ss.getSheetByName('StockPrices');
var limitA=spsh.getRange(4,2,1,spsh.getLastColumn()-1).getValues();
var nameA=spsh.getRange(1,2,1,spsh.getLastColumn()-1).getValues();
var sentA=spsh.getRange(5,2,1,spsh.getLastColumn()-1).getValues();
var msgA=[];
for(var i=0;i<pchA.length;i++) {
if(pchA[i]>limitA[i] && sentA[i]!="SENT") {
msgA.push({name:nameA[i],change:pchA[i],limit:limitA[i],index:i});
}
}
if(msgA.length>0){
var html="<h1>Stocks Exceeding Change Limit</h1>";
var text='Stocks Exceeding Change Limit\n';
for(var i=0;i<msgA.length;i++) {
html+=Utilities.formatString('<br />Stock Name: <strong>%s</strong><br />Limit: <strong>%s</strong><br />Change: <strong>%s</strong><hr width="100%"/><br />', msgA[i].name,msgA[i].limit,msgA[i].change);
text+=Utilities.formatString('\nStock Name: %s\nLimit: %s\nChange: %s\n\n', msgA[i].name,msgA[i].limit,msgA[i].change);
sentA[msgA[i].index]="SENT";
}
//GmailApp.sendEmail(recipient, 'Stocks Exceeding Change Limit', text, {htmlBody:html})
spsh.getRange(5,2,1,spsh.getLastColumn()-1).setValues(sentA);
}
}
This is what the Stock Prices page looks like:
This is what a daily data page looks like:
And this is what the timer sidebar looks like:
Apps Script Documentation
I have tried for so long now to auto calculate the sum of data attribute when adding/removing something to a shopping basket from and calculate the total of data attribute in pure JavaScript no Jquery without being able to fix it! I am pretty new to JavaScript...
Here is my code:
HTML:
//The shopping basket section
<div id="basket">Shopping Basket</div>
<ul class="cart" id="cart_id">
</ul>
<form>
<br>Total Price:
<input type="text" name="totalPrice" id="totalPrice" value="€ 0" disabled>
</form>
<div>
//The category selection section
<ul class="products" id="product_id">
<li class="cat" id="cat_id" name="data" data-title="iPad" data-price="299">iPad (€299)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="iPad Air" data-price="399">Ipad Air (€399)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="Sony Xperia Z2" data-price="399">Sony Xperia Z2 (€399)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="Samsung Galaxy Tab 10,1" data-price="349">Samsung Galaxy Tab 10,1 (€349)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
</ul>
JS :
function init(){
plus = [].slice.call(document.querySelectorAll(".plusicon"), 0);
for (var i = 0; i < plus.length; i++) {
plus[i].addEventListener("click", addToBasasket, false);
}
}
function addToBasket (e) {
e.stopPropagation();
var ele = info[plus.indexOf(this)];
var title = ele.getAttribute("data-title");
var price = parseInt(ele.getAttribute("data-price"));
var ul = document.getElementById("cart_id");
var li = document.createElement("li");
var remove = document.createElement("img");
remove.className = "removeicon";
remove.src = "removeicon.jpg";
remove.addEventListener("click", removeThingFromList, false);
li.appendChild(remove);
li.appendChild(document.createTextNode(title+" (\u20AC"+price+")"));
ul.appendChild(li);
//So when you press "plusicon" it adds to shopping basket and when you press "removeicon" it deletes from the basket!
//Here below is my problem, I have tried for so long but I cant get to work
//to show the total price when adding and removing li to basket!
var total = 0;
listItem = ele.getAttribute("data-price");
for (var i=0; i < listItem.length; i++)
{
total += parseInt(ele.getAttribute("data-price"));
}
document.querySelector("#totalPrice").value = total;
//I have tried so many different ways but can't get it to work the total of attribute("data-price")!
//This functions below works and removes the current li
function removeThingFromList(e){
this.parentNode.parentNode.removeChild(this.parentNode);
}
}
I hope someone can help! Thanks in advance!
You have to store the price in some attribute in new items (li) added to your basket :
li.appendChild(remove);
//Storing price in data-price attribute
li.setAttribute("data-price", price);
li.appendChild(document.createTextNode(title+" (\u20AC"+price+")"));
ul.appendChild(li);
And after that you can get this attribute and calculate the total :
var total = 0;
var listItem = document.getElementById("cart_id").getElementsByTagName("li");
for (var i=0; i < listItem.length; i++)
{
total += parseInt(listItem[i].getAttribute("data-price"));
}
<ul>
<li class="cart_item" data-prize="12.6" data-id="5">Hello €12.6</li>
<li class="cart_item" data-prize="4.25" data-id="8">World €4.25</li>
<li class="cart_item" data-prize="13.8" data-id="9">Foo €13.8</li>
<li class="cart_item" data-prize="6.3" data-id="12">Bar €6.3</li>
</ul>
<input type="button" value="TOTAL" onclick="calculateTotal();">
<div id="messages"></div>
<script>
function data(elm, key) {
for(var i in elm.attributes) {
if ( elm.attributes[i].name.substr(0, 5) === 'data-' ) { // checks if the 5 first letters of the attribute are 'data-'
// it's a data- attribute. Now let's see if it's the right one
if ( elm.attributes[i].name.substr(5) === key) { // checks if the letters, next to the 5 first letters, correspond with the key we need
return elm.attributes[i].value;
}
}
}
return '';
}
function calculateTotal() {
document.getElementById("messages").innerHTML = '';
var items = document.getElementsByClassName("cart_item");
var sum=0;
for (var i in items) {
var prize = Number( data(items[i], 'prize') ); // without the Number(), it's seen as text
sum += prize;
if(prize) { // else it also shows blank lines
document.getElementById("messages").innerHTML += prize + '<br>';
}
}
document.getElementById("messages").innerHTML += '+ -----<br>' + sum;
}
</script>