Javascript: inserting a variable as a parameter - javascript

I am looking at getting my "NodeNumber" variable into the parameter of my loadSynchPage function.
my code looks at the name of the page (e.g. page.htm from http://www.example.com/tree/page.htm) and after a series of lines gives a "NodeNumber". I would like the page to work out the NodeNumber and put it into the function when the page loads.
So I'd guess it would look something like this:
<BODY onload="loadSynchPage(NodeNumber);">
I have got my code to output the NodeNumber using a button with onlick.
I have also got the loadSynchPage(linkID) function, to work using a button with onclick where I enter the number myself. button and have also got a variable which I predefine to work; but I can't get it to read my "NodeNumber" and I have spent 2 days trying to figure this out.
Here is my code:
<script>
function variables() {
//Getting the page's name from the URL
PageName = location.pathname.split("/").slice(-1);
document.getElementById("PageName").innerHTML = PageName;
//Converting the page name into a string
PageNameString = String(PageName);
document.getElementById("PageNameString").innerHTML = PageNameString;
//Converting the string of the page name, into it's length
PageLength = PageNameString.length;
document.getElementById("PageLength").innerHTML = PageLength;
//Setting the DemoFramesetNodes.js as a variable (Copy and Paste in - needs to have no " and be on one line)
TextFromDemoFramesetNodesJS = "foldersTree = gFld(<i>Page 1 Title</i>, page1.htm)//000foldersTree.treeID = Framesetaux1 = insFld(foldersTree, gFld(Page 2 Title, page 2.htm)) //001insDoc(aux1, gLnk(R, Page 3 Title, Page3.htm)) //002aux1 = insFld(foldersTree, gFld(Page 4 Title, Page4.htm)) //003insDoc(aux1, gLnk(R, Page 5 Title, Page5.htm)) //004";
//Need to set the difference BETWEEN the "m" in htm and the start of the number
//e.g. page2.htm)) //001
CharacterDifference = "5";
document.getElementById("CharacterDifference").innerHTML = CharacterDifference;
//Need to find the location of the page's name from the DemoFramsetNodes
PageNameLocation = TextFromDemoFramesetNodesJS.lastIndexOf(PageNameString);
document.getElementById("PageNameLocation").innerHTML = PageNameLocation;
//Need to convert all variables to be added into numbers
PageNameLocationNumber = Number(PageNameLocation);
PageLengthNumber = Number(PageLength);
CharacterDifferenceNumber = Number(CharacterDifference);
document.getElementById("CharacterDifferenceNumber").innerHTML = CharacterDifferenceNumber;
//Add the variables to give us the start location of the Node Number
NodeNumberStart = PageNameLocationNumber + PageLengthNumber + CharacterDifferenceNumber;
document.getElementById("NodeNumberStart").innerHTML = NodeNumberStart;
//Add the variables to give us the end location of the Node Number
NodeNumberEnd = PageNameLocationNumber + PageLengthNumber + CharacterDifferenceNumber + 3;
document.getElementById("NodeNumberEnd").innerHTML = NodeNumberEnd;
//this gives us the Node Number that we want
NodeNumber = TextFromDemoFramesetNodesJS.substring(NodeNumberStart, NodeNumberEnd);
document.getElementById("NodeNumber").innerHTML = NodeNumber;
}
var avar=Number(window.NodeNumber);
//window.NodeNumber;
function loadSynchPage(linkID) {
var folderObj;
docObj = parent.treeframe.findObj(linkID);
docObj.forceOpeningOfAncestorFolders();
parent.treeframe.HightlightNode(linkID,docObj.link,'basefrm');
if (typeof parent.treeframe.document.body != "undefined") // To handle scrolling not working with NS4
parent.treeframe.document.body.scrollTop=docObj.navObj.offsetTop
}
//myvar=Number(NodeNumber);
// function loadnode(){
// document.getElementById('loadSynchPage').onclick=function(){loadSynchPage(myvar);};
// var myvar=15;
//function init(){
// document.getElementById('EditBanner').onclick=function(){EditBanner(myvar);};
// }
</script>
</head>
<BODY>
<button onclick="javascript:settingvariables();">Page Highlight1</button>
<button onclick="javascript:loadSynchPage(avar);">Page Highlight2</button>
Page Name: <p id="PageName"></p>
Page Name String: <p id="PageNameString"></p>
Page Length: <p id="PageLength"></p>
Character Difference: <p id="CharacterDifference"></p>
Page Name Location: <p id="PageNameLocation"></p>
Character Difference Number:<p id="CharacterDifferenceNumber"></p>
Node Number Start: <p id="NodeNumberStart"></p>
Node Number End: <p id="NodeNumberEnd"></p>
Node Number: <p id="NodeNumber"></p>
As you can see from the "//" near the bottom, I have already tried some different ways from other questions on stackoverflow - I am sure I have tried everything and am missing something really simple :/
I have also taken out the "var" before setting things like PageName and NodeNumber after w3 said that this would then allow them to become global variables?
To give more information:
The code is based on TreeView - it has a tree with nodes on the left and you click on the nodes to open the page in the right hand frame. However clicking on a link from a page in the right page to a different page doesn't update the highlighting on the node and that is why I am trying to do this (onload).
EDIT: If possible I would also like to get the code into an external .js and reference it as I have multiple pages (I tried this for a few hours last week with different, working code, but also couldn't get this to work either).

All you need is:
window.onload = function() {
loadSynchPage(NodeNumber);
};
Or the onload in body tag, the problem you have is that it doesn't work in the sandbox in this snippet:
Uncaught SecurityError: Sandbox access violation: Blocked a frame at
"http://stacksnippets.net" from accessing a frame at
"http://stackoverflow.com". The frame requesting access is sandboxed
and lacks the "allow-same-origin" flag.
function variables() {
//Getting the page's name from the URL
PageName = location.pathname.split("/").slice(-1);
document.getElementById("PageName").innerHTML = PageName;
//Converting the page name into a string
PageNameString = String(PageName);
document.getElementById("PageNameString").innerHTML = PageNameString;
//Converting the string of the page name, into it's length
PageLength = PageNameString.length;
document.getElementById("PageLength").innerHTML = PageLength;
//Setting the DemoFramesetNodes.js as a variable (Copy and Paste in - needs to have no " and be on one line)
TextFromDemoFramesetNodesJS = "foldersTree = gFld(<i>Page 1 Title</i>, page1.htm)//000foldersTree.treeID = Framesetaux1 = insFld(foldersTree, gFld(Page 2 Title, page 2.htm)) //001insDoc(aux1, gLnk(R, Page 3 Title, Page3.htm)) //002aux1 = insFld(foldersTree, gFld(Page 4 Title, Page4.htm)) //003insDoc(aux1, gLnk(R, Page 5 Title, Page5.htm)) //004";
//Need to set the difference BETWEEN the "m" in htm and the start of the number
//e.g. page2.htm)) //001
CharacterDifference = "5";
document.getElementById("CharacterDifference").innerHTML = CharacterDifference;
//Need to find the location of the page's name from the DemoFramsetNodes
PageNameLocation = TextFromDemoFramesetNodesJS.lastIndexOf(PageNameString);
document.getElementById("PageNameLocation").innerHTML = PageNameLocation;
//Need to convert all variables to be added into numbers
PageNameLocationNumber = Number(PageNameLocation);
PageLengthNumber = Number(PageLength);
CharacterDifferenceNumber = Number(CharacterDifference);
document.getElementById("CharacterDifferenceNumber").innerHTML = CharacterDifferenceNumber;
//Add the variables to give us the start location of the Node Number
NodeNumberStart = PageNameLocationNumber + PageLengthNumber + CharacterDifferenceNumber;
document.getElementById("NodeNumberStart").innerHTML = NodeNumberStart;
//Add the variables to give us the end location of the Node Number
NodeNumberEnd = PageNameLocationNumber + PageLengthNumber + CharacterDifferenceNumber + 3;
document.getElementById("NodeNumberEnd").innerHTML = NodeNumberEnd;
//this gives us the Node Number that we want
NodeNumber = TextFromDemoFramesetNodesJS.substring(NodeNumberStart, NodeNumberEnd);
document.getElementById("NodeNumber").innerHTML = NodeNumber;
}
var avar=Number(window.NodeNumber);
//window.NodeNumber;
function loadSynchPage(linkID) {
alert("loadSynchPage called");
var folderObj;
docObj = parent.treeframe.findObj(linkID);
docObj.forceOpeningOfAncestorFolders();
parent.treeframe.HightlightNode(linkID,docObj.link,'basefrm');
if (typeof parent.treeframe.document.body != "undefined") // To handle scrolling not working with NS4
parent.treeframe.document.body.scrollTop=docObj.navObj.offsetTop
}
loadSynchPage(NodeNumber);
//myvar=Number(NodeNumber);
// function loadnode(){
// document.getElementById('loadSynchPage').onclick=function(){loadSynchPage(myvar);};
// var myvar=15;
//function init(){
// document.getElementById('EditBanner').onclick=function(){EditBanner(myvar);};
// }
<button onclick="javascript:settingvariables();">Page Highlight1</button>
<button onclick="javascript:loadSynchPage(avar);">Page Highlight2</button>
Page Name: <p id="PageName"></p>
Page Name String: <p id="PageNameString"></p>
Page Length: <p id="PageLength"></p>
Character Difference: <p id="CharacterDifference"></p>
Page Name Location: <p id="PageNameLocation"></p>
Character Difference Number:<p id="CharacterDifferenceNumber"></p>
Node Number Start: <p id="NodeNumberStart"></p>
Node Number End: <p id="NodeNumberEnd"></p>
Node Number: <p id="NodeNumber"></p>
2nd question: Save all the script (not including the <script> tags) to myjs.js, put it to the same directory next to page.html, and remove the whole <script> block from html, and put this instead of it:
<script src="myjs.js"></script>

Related

Dynamic JS/HTML elements appear out of order only in GAS? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have a dynamic HTML form that I generate from Google Apps Script. I expect the elements to appear in the same order that they appear in the input object, which is the same order by which I append the elements. But the elements actually appear in an unexpected order.
I followed this other post to try to sort this out but the elements still appear out of order when I run my code in GAS. The thing is, when I run my code in jsfiddle, it works as expected, i.e. the elements appear in the same order as they do in the input object. The elements just don't order as expected in GAS.
Why do the elements appear out of order in GAS but appear in order in jsfiddle? How do I resolve this in GAS using vanilla JS?
Copy of jsfiddle code:
HTML
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<div id='input_parent'></div>
</body>
<br><input type="button" value="Submit" onClick="test()">
</form>
JS
inputObj = {"first field":{"required":true,"dataType":"select","options":["first opt","second opt"]},"second field":{"required":true,"dataType":"text","options":"none"}}
// Section
section = document.getElementById("input_parent");
div = document.createElement("div");
div.setAttribute("id", "input_child");
section.appendChild(div);
var fields = Object.keys(inputObj);
Array.from(fields).forEach((arg) => {
// Label
section = document.getElementById("input_parent");
label = document.createElement("label");
label.setAttribute("id", "label_"+arg);
label.setAttribute("for", arg);
label_txt = document.createTextNode(arg+":");
label.appendChild(label_txt);
section.appendChild(label);
if (inputObj[arg].dataType == "select") {
// Create select element
section = document.getElementById("input_parent");
const select_element = document.createElement("select");
select_element.setAttribute("id", "select_"+arg);
section.appendChild(select_element);
var options = inputObj[arg].options
for(let o = 0; o < options.length; o++)
{
var element = document.getElementById("select_"+arg);
const option = document.createElement("option");
var text = document.createTextNode(arg+":");
option.textContent = options[o];
option.setAttribute("value", options[o]);
element.appendChild(option);
};
} else {
section = document.getElementById("input_parent");
input_field = document.createElement("input");
input_field.setAttribute("id", "input_"+arg);
input_field.setAttribute("type", inputObj[arg].dataType);
section.appendChild(input_field);
}
});
Additional info in response to #Nikko J. The following code should reproduce the results in the images below.
dynamHtmlTbrlsht.html to render form.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id='input_parent'></div>
</body>
<br><input type="button" value="Submit" onClick="test()">
</html>
<script type='text/javascript'>
window.onload = function(){
google.script.run.withSuccessHandler(addElements).getElementInfo();
}
</script>
<script type='text/javascript'>
function addElements(inputObj) {
// Section
section = document.getElementById("input_parent");
div = document.createElement("div");
div.setAttribute("id", "input_child");
section.appendChild(div);
var fields = Object.keys(inputObj);
Array.from(fields).forEach((arg) => {
// Label
section = document.getElementById("input_parent");
label = document.createElement("label");
label.setAttribute("id", "label_"+arg);
label.setAttribute("for", arg);
label_txt = document.createTextNode(arg+":");
label.appendChild(label_txt);
section.appendChild(label);
if (inputObj[arg].dataType == "select") {
// Create select element
section = document.getElementById("input_parent");
const select_element = document.createElement("select");
select_element.setAttribute("id", "select_"+arg);
section.appendChild(select_element);
var options = inputObj[arg].options
for(let o = 0; o < options.length; o++)
{
var element = document.getElementById("select_"+arg);
const option = document.createElement("option");
var text = document.createTextNode(arg+":");
option.textContent = options[o];
option.setAttribute("value", options[o]);
element.appendChild(option);
};
} else {
section = document.getElementById("input_parent");
input_field = document.createElement("input");
input_field.setAttribute("id", "input_"+arg);
input_field.setAttribute("type", inputObj[arg].dataType);
section.appendChild(input_field);
}
});
}
</script>
trblsht.gs to create input object. (Note that this is simplified for resolving the problem at hand. In reality, inputObj is generated by running a few functions that dynamically create the object and fetch options from an external source.)
function getElementInfo() {
var inputObj = {"first_fild":{"required":true,"dataType":"select","options":["option 1","option 2","option 3","option 4"]},"second_field":{"required":true,"dataType":"text","options":"none"},"third_field":{"required":true,"dataType":"text","options":"none"},"fourth_field":{"required":true,"dataType":"text","options":"none"},"fifth_field":{"required":false,"dataType":"select","options":["option 1","option 2","option 3","option 4","option 5","option 6","option 7","option 8","option 9","option10"]},"sixth_field":{"required":false,"options":"none"},"seventh_field":{"required":false,"dataType":"select","options":["option 1","option 2","option 3","option 4","option 5","option 6"]}}
Logger.log("inputObj: "+JSON.stringify(inputObj))
return inputObj;
}
For completeness, the following lines are in an onEdit function that generates the form when the active cell == "troubleshoot".
function myOnEditTriggerFunc() {
// do other stuff
var currentRange = SpreadsheetApp.getActiveRange();
var currentVal =
currentRange.getValue().toString().replace(/(^\s+|\s+$)/g,"");
if (currentVal == "troubleshoot") {
openHTML("dynamHtmlTbrlsht","Troubleshoot",400)
return;
}
}
openHTML() referenced in above function.
function openHTML(htmlFile,htmlTitle,height) {
var html = HtmlService.createHtmlOutputFromFile(htmlFile)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setHeight(height);
SpreadsheetApp.getUi()
.showModalDialog(html, htmlTitle);
return;
};
Output form showing unexpected order of elements:
Output log showing expected order of elements:
The jsfiddle shows the normal js.
I started to wonder if the issue is with Array.from(fields).forEach((arg) in dynamHtmlTbrlsht.html. I intentionally used Array instead of Object since Array is ordered whereas Object is not always ordered (depends on ES). Maybe there's something related to V8 runtime that's affecting this and I'm not picking up on?
When I saw your script, I thought that the reason for your issue is due to that the data is a JSON object. When the document about JSON is seen, it says as follows. Ref
In JSON, they take on these forms:
An object is an unordered set of name/value pairs. An object begins with {left brace and ends with }right brace. Each name is followed by :colon and the name/value pairs are separated by ,comma.
And, in your script, the values are retrieved from the JSON object using var fields = Object.keys(inputObj). In order to confirm this using your script, when console.log(Object.keys(inputObj)) is put after the line of function addElements(inputObj) { at Javascript side and before the line of return inputObj; at Google Apps Script side, each log shows as follows.
For Javascript side, it's ["fourth_field", "seventh_field", "second_field", "sixth_field", "third_field", "fifth_field", "first_fild"].
For Google Apps Script side, it's ["first_fild","second_field","third_field","fourth_field","fifth_field","sixth_field","seventh_field"].
It is found that the order of keys is different between the Javascript side and Google Apps script side. I thought that this might be the reason for your issue.
If you want to use the order of ["first_fild","second_field","third_field","fourth_field","fifth_field","sixth_field","seventh_field"], how about the following modification?
Modified script 1:
In this pattern, the keys are set as an array in order.
Google Apps Script side:
From:
return inputObj;
To:
return [inputObj, ["first_fild","second_field","third_field","fourth_field","fifth_field","sixth_field","seventh_field"]];
Javascript side:
From:
function addElements(inputObj) {
// Section
section = document.getElementById("input_parent");
div = document.createElement("div");
div.setAttribute("id", "input_child");
section.appendChild(div);
var fields = Object.keys(inputObj);
To:
function addElements([inputObj, fields]) {
// Section
section = document.getElementById("input_parent");
div = document.createElement("div");
div.setAttribute("id", "input_child");
section.appendChild(div);
// var fields = Object.keys(inputObj);
Modified script 2:
In this pattern, the keys are set as Object.keys(inputObj) in order. By this, the same order can be used between the Google Apps Script side and the Javascript side.
Google Apps Script side:
From:
return inputObj;
To:
return [inputObj, Object.keys(inputObj)];
In this pattern, the modification of the Javascript side is the same as pattern 1.

Fetching values from an element in an iframe on the same domain

I'm trying to condense two processes down in to one by having the two pages I need on one page using an iframe.
I have a page that contains a text area (used for sending an email) and then I have a purchase reference page that contains the details of someones purchase.
I'm trying to append an iframe of the purchase page to the bottom of my email page and then grab some data that's on it and insert it in to the text area.
EDIT: This is what I have so far:
Script one
//Grabs the selected purchase number
var purchaseNumber = window.getSelection();
purchaseNumber = purchaseNumber.toString();
var purchaseTitle;
var purchaseNumber;
function frameLoaded() {
purchaseTitle = window.frames['purchaseIframe'].contentDocument.getElementById ('listingTitle');
purchaseNumber = window.frames['purchaseIframe'].contentDocument.getElementById ('auctionSoldIdDisplay');
purchaseTitle = purchaseTitle.innerHTML;
purchaseNumber = purchaseNumber.innerHTML
var purchaseDetails = purchaseTitle + " - " + purchaseNumber;
insertText = insertText.replace("PURCHASEDETAILS", purchaseDetails);
}
if(purchaseNumber.length > 0){
var purchaseIframe = document.createElement('iframe');
purchaseIframe.src = 'http://www.mysite.co.nz/Admin/Listing/PurchaseDisplay.aspx?asid=' + purchaseNumber + '&submit1=++GO++';
purchaseIframe.setAttribute("height","1000");
purchaseIframe.setAttribute("width","100%");
purchaseIframe.setAttribute("id","purchaseIframe");
purchaseIframe.setAttribute("onload", "frameLoaded();");
void(document.body.appendChild(purchaseIframe));
alert(purchaseNumber);
}
Script Two
//Gather the selected template
var selectedTxt = document.getElementById('txtEmailText').value;
//Change the selected txt to a string
var insertText = selectedTxt.toString();
var purchaseTitle = window.frames['purchaseIframe'].contentDocument.getElementById ('listingTitle');
var purchaseNumber = window.frames['purchaseIframe'].contentDocument.getElementById ('auctionSoldIdDisplay');
purchaseTitle = purchaseTitle.innerHTML;
purchaseNumber = purchaseNumber.innerHTML
var purchaseDetails = purchaseTitle + " - " + purchaseNumber;
insertText = insertText.replace("PURCHASEDETAILS", purchaseDetails);
//Pasting the variable in to the textarea
document.getElementById('txtEmailText').value = insertText;
Effectively I am highlighting the purchase reference number on the page then executing this script to open the purchase page using the highlighted number. I am then grabbing the text values of the elements I need and pasting them in to the text area.
I'm still pretty new to javascript and am teaching myself as I go.
If i run the above scripts one after the other then it works like a charm, however if I try to run them together with the second in an onload() function set to the iframe then it won't.
Any help would be greatly appreciated or if you could point me in the direction of an article to help.
My first thought is that the iframe is not fully loaded before you try to get the values from it. My thought would be to try adding an onload event to your iframe and then when it loads invoke a function that grabs the value.
I would add purchaseIframe.setAttribute("onload", "frameLoaded();"); to your purchaseIframe block and then add the frameLoaded() function to your script. something like:
function frameLoaded() {
var purchaseTitle = window.frames[0].document.getElementById("listingTitle" );
var purchaseNumber = window.frames[0].document.getElementById("auctionSoldIdDisplay");
console.log(purchaseTitle.innerHTML);
console.log(purchaseNumber.innnerHTML);
}
And see if something like that grabs the right values. If it does than you can plug it in where you need it.
Am I understanding your problem correctly?

global site variable js

I am new to javascript, i am trying to make a small site with two HTML pages (A and B) and a global js file.
So lets say i have selected certain items in page A, the list-preview on Page A gets updated.
But if i want to see the list in detail i have to go to page B.
Page A and B bith use the same .js file, the selected items are saved in a array.
How do i make sure the selected items still stay in the array, and the array doesn't get flushed when i go from page A to page B ?
what i thought of was ...
var selectedProductsName = new Array();
in OwnJS.js
the adding items to the preview list works.
i'm only struggling to keep the array unflushed when i go to page B from page A.
HTML5 introduces a new thing called localStorage. It's basically some kind of storage that is persistent between all pages of your website as well as between user sessions. It can be accessed as a simple key/value store:
var selectedProductsName = localStorage.getItem("selectedProductsName");
And to set:
localStorage.setItem("selectedProductsName", []);
Here's an article about getting started with localStorage, if you want to be able to do more things like checking browser compatibility for localStorage and watching the storage event, among others.
You could use the HTML5 local storage. It lets you tell the browser to save data on the user's machine. (There's also session storage, valid only for the current session.)
Save (in Apply.html)
IN.API.Profile("me")
.fields(["id", "firstName", "lastName", "pictureUrl","headline","industry","location:(name)","positions:(title)","emailAddress"])
.result(function(result) {
profile = result.values[0];
// save all keys to local storage
for (f in profile) localStorage[f] = fields[f];
// more stuff ...
});
to Retrieve (in personal_Info.html)
// retrieve first name from local storage
var firstName = localStorage["firstName"];
if (firstName !== undefined) {
$("#textfield1").attr(value, firstName);
}
Source Page
The Source Page has an HTML Button with a jQuery Click event handler. When the Button is clicked, the values of the Name TextBox and the Technology DropDownList is set as QueryString Parameter and then the page is redirected to the Destination page (Page2.htm).
<input type="button" id="btnQueryString" value="Send" />
<script type="text/javascript">
$(function () {
$("#btnQueryString").bind("click", function () {
var url = "Page2.htm?name=" + encodeURIComponent($("#txtName").val()) + "&technology=" + encodeURIComponent($("#ddlTechnolgy").val());
window.location.href = url;
});
});
</script>
Destination Page
On the Destination page (Page2.htm), inside the jQuery Page Load event handler the URL of the page is first checked to determine whether it has some QueryString Parameters being received, this is done by checking the window.location.search property. If it has some QueryString Parameters then loop is executed and each QueryString Key and Value Pair is inserted in an Array and finally the values are displayed on the page using the HTML span.
<script type="text/javascript">
var queryString = new Array();
$(function () {
if (queryString.length == 0) {
if (window.location.search.split('?').length > 1) {
var params = window.location.search.split('?')[1].split('&');
for (var i = 0; i < params.length; i++) {
var key = params[i].split('=')[0];
var value = decodeURIComponent(params[i].split('=')[1]);
queryString[key] = value;
}
}
}
if (queryString["name"] != null && queryString["technology"] != null) {
var data = "<u>Values from QueryString</u><br /><br />";
data += "<b>Name:</b> " + queryString["name"] + " <b>Technology:</b> " + queryString["technology"];
$("#lblData").html(data);
}
});
</script>

Stop a page from refreshing after firing a function

I've been tasked with building a very simple app that that has a series of dropdowns in rows of 2, when 2 are selected, a simple functions concatenates the 2 values and gives an output next to them like so:
dropdown1 dropdown2 Output
What I'm trying to get is, once the second dropdown value is chosen the function runs and displays the output where it says output. But currently, what seems to happens is the output is displayed in a new window.
Here's what I have so far (HTML):
<form>
<select id="test">
<option>Arena/Quantum Barcelona LTBC</option>
<option>Arena/Quantum Spain LTES</option>
</select>
<select id="name" onchange="tryThis()">
<option>Name</option>
<option>Name1</option>
</select>
</form>
JavaScript:
function tryThis() {
var string, string1 = '';
var e = document.getElementById("test");
string = e.options[e.selectedIndex].text;
var a = document.getElementById("name");
string1 = a.options[a.selectedIndex].text;
document.write(string+'_'+string1);
}
Am I making this more difficult than it needs to be?!
That's because document.write clears the page before displaying something. You should never need to use that function.
Instead, you could append it to e.g. the body:
document.body.appendChild(
document.createTextNode(string + '_' + string2)
);
Have you noticed that your JS function is called tryThis() and on the event handler you're calling tryThsis()
However in your case I'd refrain from using document.write, good alternatives are appending to the body or having a DIV and changing the innerHTML of that DIV
First put an id on your form so that it is easier to access.
var a = (function () {
var myForm = document.getElementById("myForm"),
magic = function () {
var a = myForm.getElementsByTagName("select"),
b,
c = [];
for (b = a.length - 1; b > -1; b -= 1) {
c.push(a[b].value);
}
alert(c.join(" ") + " output");
};
myForm.onclick = magic;
}());
You were not specific as to what the extra "output" is supposed to be or how you want the data returned, but here you go. Instead of using an alert you could push the result into the value of a different form element. Do not use document.write as this cannot be deferred. If you attempt to defer a document.write operation it will replace the entirety of the body contents of the current page.

How can I reduce this Javascript/HTML/jQuery code?

I have hundreds, maybe thousands of charts for stores. The only difference is the name of the store and the product. The HTML code is dynamically generated once/day. Even minified, it takes forever to load (at least it feels like an eternity). If I use Firebug, then loading the file does take a very, very long time to load.
The stores and products are created from a table that's generated each morning. Since each table has a title (e.g., "JohnsMarket"), the ids cannot be reduced to numbers (e.g., 'store1', 'store2').
All of the other SO solutions to repetitive code use numbered ids.
For each store/product, I have to repeat the following 3 snippets.
<div id="JohnsMarket_Soup" class="frmStep">
<div id="JohnsMarket_soup_chart" ></div>
<div class="layout">
<div class="layout_slider-settings">
<div class="loading" id="JohnsMarket_soup_loading"></div>
</div>
<div class="layout_slider"><input id="JohnsMarket_soup_slider" name="area" value="1" ></div>
<div class="layout_slider-settings"> </div>
</div>
</div>
if ( ui.panel.id==='JohnsMarket' )
{
if( typeof JohnsMarket_soup_chart_data === 'undefined' )
{
$('.loading_graph_msg').show();
window.setTimeout(function() { JohnsMarket_soup_data=checkData( JohnsMarket_soup_data,'JohnsMarket' );
JohnsMarket_soup_chart_data = createChart(JohnsMarket_soup_data, 'JohnsMarket_soup_chart', 'JohnsMarket Soup', 50, 7, -1); },50 );
$('.loading_graph_msg').hide('fast');
}
}
});
jQuery('#JohnsMarket_soup_slider').slider({}
$('#JohnsMarket_soup_loading').show();
var x = this.getValue();
window.setTimeout(function() {
JohnsMarket_soup_chart_data.replot();
JohnsMarket_soup_chart_data.destroy();
JohnsMarket_soup_chart_data = createChart(JohnsMarket_soup_data, 'JohnsMarket_soup_chart_data', 'JohnsMarket Soup', 5, x*7, -1);
},20 );
}
});
I can't say I fully understand what your whole problem statement looks like, but you can drastically compress all your code into one function that is used over and over again. This will, at least trim the size of the code down. Since you only showed one example of the data, I can't be sure what exactly is common from one data set to the next, but I made an assumption in order to show you how it can all be procedurized. You could collapse all the code to this:
function checkItem(idStr) {
if ( ui.panel.id == idStr) {
// generate derived names
var soupChartDataName = idStr + "_soup_chart_data";
var soupDataName = idStr + "_soup_data";
var soupChartData = idStr + "_soup_chart_data";
var soupChart = idStr + "_soup_chart";
var soup = idStr + " Soup";
var soupSlider = idStr + "_soup_slider";
var soupLoading = idStr + "_soup_loading";
if (typeof window[soupChartDataName] === 'undefined') {
$('.loading_graph_msg').show();
window.setTimeout(function() {
window[soupDataName] = checkData(window[soupDataName], idStr );
window[soupChartData] = createChart(window[soupChartData], soupChart, soup, 50, 7, -1);
}, 50);
$('.loading_graph_msg').hide('fast');
}
$("#" + soupSlider).slider({});
$("#" + soupLoading).show();
var x = this.getValue();
window.setTimeout(function() {
window[soupChartDataName].replot();
window[soupChartDataName].destroy();
window[soupChartDataName] = createChart(soupDataName, soupChartData, soup, 5, x*7, -1);
}, 20);
}
}
checkItem("JohnsMarket");
Then, for all the other items just call checkItem() with a different idString and no additional code. If I didn't guess the commonality among them quite correctly, you should be able to get the idea for how you can generate all the names being used from one or two common roots. For example, if "soup" isn't common among all the derived names, then maybe you need to pas that root into checkItem too so it can vary from one name to the next. If this were my code, I wouldn't be using so many global variables and I'd hang them off some object in my page, but that's your choice.
Note - for global variables, we access them off the windowobject so we can use the derived variable names as indexes.
And, you could create the HTML from a string template like this:
function createItem(idStr) {
var template = '<div id="xxxx_soup_chart" ></div><div class="layout"><div class="layout_slider-settings"><div class="loading" id="xxxx_soup_loading"></div></div><div class="layout_slider"><input id="xxxx_soup_slider" name="area" value="1" ></div><div class="layout_slider-settings"> </div></div>';
var o = document.createElement("div");
o.id = idStr + "_Soup";
o.className = "frmStep";
o.innerHTML = template.replace(/xxxx/g, idStr);
document.body.append(o); // change this to append the item wherever it's supposed to go
}
createItem("JohnsMarket");
Any of that data seems like it could be stored in a hash keyed on the store name, including the chart itself; the rest is just string concatenation. But I agree, I'd try to move some of that onto the server side, even if it's just to retrieve the data used to create the charts.

Categories

Resources