Let me start by saying, that while I have some programming experiencing (some basic C from a college class and I once wrote a FORTRAN programm in college for a professor), I am utterly new to JS and beginning to get a bit frustrated.
For some reason, even after reading tutorials and watching several YouTube videos on objects, I seem unable to wrap my head around it. I understand the fundamentals and have no problems doing very basic stuff, like writing a loop that prints out increments on a HTML site, but every time I try something practical, I am completely at a loss.
Here is my current problem: I have created this HTML site that generates a shopping list. Basically, when I click on one of the buttons next to an item name, it adds that item to the list in the middle of my screen. Thanks to Google I found a piece of JavaScript code which, through try and error, I managed to tweak for this purpose:
<!-- click this button to add the item-->
<button onclick="myFunction('ITEM1', 100)" class="sidebarbuttons" >ITEM1 </button>
/* Create a List one line at a time- */
<script>
function myFunction( x, y ) {
var node = document.createElement("LI" );
var textnode = document.createTextNode(x);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
}
</script>
So far, so good. Now I want to get the net price for all the items. Which means, When I click the button, I want a function to add the price of that item to a variable and then display that variable in a field with
document.getElementById("result").innerHTML = total_sum;
Here's my question: how, oh my god, how do I do this? I thought I could add the following:
function myfunction(x,y){
var sum = 0;
var sum+=y;
}
document.getElementById("result").innerHTML = 'sum';
Obviously, this doesn't work at all. Can you please give me some hints what I have to do to make this work?
First of all,
please consider to study JavaScript better, because it's a falsy easy programming language and it's very dangerous to copy&paste without knowing the language. It's quite normal to read a lot, watch a lot and don't know where to start, and it's the main reason because people hates JavaScript: because we don't know well JavaScript. So consider to read the book series "You Don't Know" by Kyle Simpson.
About your question. You can add a variable to storage the sum of your items and when you click to an item, you can add to it:
var total_sum = 0;
function myFunction( x, y ) {
var node = document.createElement("LI" );
var textnode = document.createTextNode(x);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
showResults(y);
}
function showResults(price){
total_sum += parseFloat(price)
document.getElementById("result").innerHTML = total_sum;
}
JSBIN
Let me know ;)
So you are on the right track. Picking up where you left off in your last code block, there are few things you will need to change.
//declare the variable outside of the function... otherwise it will only be available to you within that function.
var totalSum = 0;
// then within your function you will be able to successfully add to the global totalSum variable
function calculateSum(x){
totalSum += x;
// and lastly... set the innerHTML within the function... which should equal the variable totalSum
document.getElementById("result").innerHTML = totalSum;
}
Hope this helps.
Related
I am at starting web dev, already using html/css.
For a little project, I had a look at JavaScript. (My goal is that when people click a button, the site will show a random sentence that will be taken from a google sheet cell.)
Could you tell me please if it is even possible? If so, please share some ideas that I will explore. If not, please give me some alternative ideas... Thanks so much.
Have a good day!
-LeganV9
This is possible using Google Apps Script!
I have a working demo here, with the source being here. I dare you to get the jackpot. :D
In order to make this, you can go to https://script.new. Now, in code.gs put this:
function doGet() {
return HtmlService.createTemplateFromFile("index").evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
function getVals(){
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1IDbhQhaImcQB-4j-iByajwAkvxkutptcPMhMTxNrPtU/edit#gid=0");//Put your URL here
var sheet = ss.getSheetByName("Sheet1");//Put your sheet name here
var AMOUNT_OF_SENTENCES = sheet.getMaxRows().toString().replace(".0","");//You can replace this with a number eg 20
var range = sheet.getRange(1, 1,AMOUNT_OF_SENTENCES);
var values = range.getValues();
var newValues = [];
for(var i = 1; i<values.length;i++){
if(values[i][0] === "" || values[i][0] === " "){
}else{
newValues.push(values[i][0]);
}
}
return {valuesVar: newValues };
}
After that, create a new HTML file called "index" and put this in it:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>
The results are: <span id = "results">Loading...</span>
</h1>
<button id = "yourIdHere">Click me!!</button>
<script>
var yourDataList;
function onSuccess(data) {
yourDataList= data.valuesVar;
}
google.script.run.withSuccessHandler(onSuccess).getVals();
var myBtn = document.querySelector("#yourIdHere"); //Declare button, replace yourIdHere with your ID
var randomNum = 0; //Decclre random number
function getRandom() { //Declare your function
randomNum = parseInt(Math.random() * yourDataList.length); //Get random number between 0 and the length of your datalist
return yourDataList[randomNum]; //Return your value
}
myBtn.addEventListener("click", function() { //Bind a listener to the button
document.querySelector("#results").innerText = getRandom(); //Do whatever you want to with the random value
});
document.querySelector("#results").innerText = getRandom();//Change from loading...
</script>
</body>
</html>
Welcome to the world of web development! Hope your project is a success.
It should definitely be possible, since Google Sheets offers an API which has read/write functionality (https://developers.google.com/sheets/api).
You could even later extend this so people can submit their own sentences, given that writing to a Google Sheet is also possible with this API.
However, since you're starting out, consider treating this as an iterative process. You don't have to publish your first version, but just to prevent overwhelming yourself, you might want to set small milestones along the way - each adding more functionality. For example:
Create an array of random sentences (you could, for example, start with using this to keep it simple: https://github.com/JamesFT/Database-Quotes-JSON).
Select and log a random sentence to the console (console.log()) each time the script is executed.
Transfer the random sentence to render in HTML and allow a new sentence to be generated each time a button is pressed.
Move your sentences into a Google Sheet and begin exploring the API.
This way, you achieve something in a much shorter space of time, while working towards your end goal. It's a good way to keep motivated and make things more manageable.
Best of luck!
I have written a very simple code on my Google Sheets file. This is the purpose:
Save some cells values from StaticSheet (all the Copyxxx) that need to be copied in DynamicSheet.
Get the value of one specific cell inserted by the user manually.
Enter a While loop useful only to increase an indicator and get the number of the row where I want to copy those values previously saved.
Copy those values on this row but different columns.
The problem is that it seems that most of the time it does not even run the script after I told it to do so.
What is funny is that sometimes it works, super slowly, but it works for like a couple of minutes. And after it stops working again.
Could you please tell me what am I missing here please?
function Copy_Static_on_Dynamic() {
var app = SpreadsheetApp;
var ss = app.openById("xxxxyy--------yyzzzz")
var StaticSheet = ss.getSheetByName("DEAT Price");
var DynamicSheet = ss.getSheetByName("DEAT Price + TEST");
var CopySKU = StaticSheet.getRange(5,1,40);
var CopyPrices = StaticSheet.getRange(5,3,40,4);
var CopyUsage = StaticSheet.getRange(5,8,40);
var Week_1 = StaticSheet.getRange(2,4).getValues();
var i = 1;
Logger.clear();
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
{
Logger.log(i);
i+=1;
}
CopySKU.copyTo(DynamicSheet.getRange(i,4,40));
CopyPrices.copyTo(DynamicSheet.getRange(i,6,40,4));
CopyUsage.copyTo(DynamicSheet.getRange(i,11,40));
}
If you see the "Preparing for Execution" message in the Apps Script editor, you can reload the browser window and run the function again. The program will likely go away.
So I think I have solved it.
As Serge insas was saying I had my script running on the background, I found it out on the "Execution" section, where you can also interrupt them.
After I discover it I kept testing, and I saw that the while loop needed almost 2 seconds to check the condition every time, making the script incredibly long.
So instead of:
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
... I have created a variable declared previously such as:
var WeekLOOP = DynamicSheet.getRange(i,3).getValues();
while(WeekLOOP != Week_1) { --- }
... and now the script needs few milliseconds to run the condition. I don't have enough technical knowledge to say if this was the only issue, but is what apparently solved my problem.
Thanks to all for the support! Will come back if I need any further help :)
As was mentioned by Amit Agarwal, to solve the error message mentioned on the question, refresh the web browser tab.
Regarding the code,
On
var Week_1 = StaticSheet.getRange(2,4).getValues();
and
DynamicSheet.getRange(i,3).getValues()
instead of getValues you should use getValue because your code are referring to single cell cells otherwise you will be getting 2D arrays instead of scalar values.
The use of while should be made very carefully to avoid functions running endlessly. You could add some "safeguard" like the following
var max_iterations = 100 // Edit this
while(DynamicSheet.getRange(i,3).getValue() != Week_1 && i <= max_iterations) {
First off: sorry for that awful Code. I am an absolute beginner and this is my very first JS code ever and I had to code it under time-pressure (not good).
The task was to code a guest book. I have a function that creates a new div per entry and appends it to the last one (this part works well).
var lastid = 2;
function eintragen() {
...
var divC = document.createElement('div');
var ident='item'+lastid;
divC.innerHTML = '<table id="'+ident+'" class="eintrag center">
<tr><td>Name:</td><td>'+name2+'</td></tr><tr>
<td>Email:</td><td>'+email2+'</td></tr>
<tr><td>Eintrag</td><td>'+nachricht2+'</td></tr>
<tr><td></td><td><button class="buttonklein"value="loeschen"
***onclick="loeschen('+ident+')"***
>Eintrag löschen</button></td></t></table><hr>';
**divC.setAttribute('id',ident);**
var add = document.getElementById('item1');
add.appendChild(divC);
lastid+=1;
...
}
I tried do highlight the relevant part. As you can see, I gave the id to the divC twice, because after testing, I figured out, that it did not work in the "divC.innerHTML"-segment.
Every entry has an own delete-button, which should - you guess it - delete that associated entry.After clicking the button, the function starts, but then nothing happens.
function loeschen(itemid) {
var sitem = document.getElementById(itemid);
sitem.parentNode.removeChild(sitem);
}
I guess, since assigning the ID to the divC did not work in the "divC.innerHTML" part, it also does not work to assign it as a parameter to the "onclick" -attribute.
If I replace itemid with something concrete like 'item4' in the loeschen-function, it does delete entry number 4, so I guess the mistake is in the divc.innerHTML-part.
Question: Where did I go wrong? Any wrong '' oder ""? How can i give every button the current itemid? everything worked fine for the other variables like name oder email, so I have absolutely no clue.
Thanks so much in advance and sorry for my bad style. I will work on this in the future.
User Teemu found the answer super fast and was a great help.
It was indeed bad syntax in the divC.innerHTML-segment.
This does the job:
divC.innerHTML = `<table id="${ident}" class="eintrag center">
<tr><td>Name:</td><td>${name2}</td></tr><tr>
<td>Email:</td><td>'+email2+'</td></tr>
<tr><td>Eintrag</td><td>${nachricht2}</td></tr>
<tr><td></td><td><button class="buttonklein" value="loeschen"
onclick="loeschen('${ident}')">Eintrag löschen</button>
</td></t></table><hr>`;
I'm writing a chrome extension that will add helper text instructions/reminders to specific location in the "new order" form we use at work. I'm really new to coding (basically using this project as a way to learn). I've created something that works - but I'm convinced there's a more elegant solution that I just haven't been able to figure out.
var helpText = "this is the message"
var customAlert = makeAlert(helpText) //create html container for msg
function makerAlert(helpText){...} //createElem, add class/style, append children
I'm okay with that bit (above). But should i be storing information on each message in objects instead? why would/wouldn't i? what information would go in it?
function alertPlacer(customAlert){
var par = document.getElementsByClassName("class-name")[i];
var sib = par.childNodes[j];
par.insertBefore(customAlert, sib);
};
really struggling with this bit (above). I have actually made alertPlacer() functions for each message because i can't figure out how to create a function that will take different class name & index parameters. should i be breaking this up more? if i stored these bits of info in an object, would that be useful?
relevant info:
because the target locations are within a form, almost nothing has an "id" attribute. so i have to use getElementsByClassName & an index.
for each message, I know the target parent className & index and the child node index to "insert before".
i would like to stick with javascript-only solution.
functions can take multiple arguments:
function alertPlacer(customAlert,className,parIndex,childIndex){
var par = document.getElementsByClassName(className)[parIndex]; var sib = par.childNodes[childIndex];
par.insertBefore(customAlert, sib);
};
And you call your function like
alertPlacer(yourAlert,"class-name",6,9);
ok. I have a dropdown. well call it dropdownA. I have several arrays already fashioned, that i want to loop through, and put each individual value out onto the page into it's own input field, based on the selection in the dropdown. I know how to put together the loop to get the values out onto the page. anyway, here is the meta code.
meta1array=new Array('','','','','','');
meta2array=new Array('','','','','','');
meta3array=new Array('','','','','','');
function metacode(id){
{
var a=get.the.dd.selIndex;
var b=get.the.dd.options[a].value; //comes back as 'meta1'. other opts are meta2, meta3
var c=b+'array';
for(i=0;i<c.count;i++)
{
loop here to popout values
}
}
i have looked everywhere, and i haven't come up with anything. I also admit that my brain is starting to mushify from a few weeks straight of coding, and this is the first time i have come across this. so, please. i would be greatful for any help.
Global variables are members of the window object.
var c = window[b + 'array'];
It might be wise to make your arrays members of some other object though, for tighter scoping (avoid cluttering the global namespace).
metaobject = {
meta1array: ['','','','',''],
meta2array: ['','','','',''],
meta3array: ['','','','','']
};
// snip
var arr = metaobject[b + 'array'];
for(var i=0;i<arr.length;i++) {
//do work
}
Check out the fiddle using jquery here.