JavaScript Array & Global Variable Reference - javascript

I am trying to reference a global variable's value using my array output but I am unsure how to do that. I want to make these references outside the function as I will need to create many functions that use these variables.
Ignore the PFGetValue part, I need to use that for the program I am coding in. There will be many more dd_meg_x but this is just to show you what I'm doing. Currently, this will return the correct the text "dd_meg_x" - but I want to then reference the variable defined above. So for example, if the result in the array is dd_meg_1, I want the output to be "M Energy 16"
var dd_meg_1 = "M Energy 16";
var dd_meg_2 = "Ulra Energy";
var dd_meg_3 = "Another Option Here";
function canOrderMeg1() {
var brand = "meg";
var arrayLength = 21;
var canArray = [];
var variableName;
for (i = 0; i <= arrayLength; i++) {
variableName = ("dd_" + brand + "_" + i);
if (PFGetValue(variableName) === "Y") {
canArray.push(variableName);
}
canArray.join(", ");
}
return canArray[0];
}
function canOrderMeg2() {
var brand = "meg";
var arrayLength = 21;
var canArray = [];
var variableName;
for (i = 0; i <= arrayLength; i++) {
variableName = ("dd_" + brand + "_" + i);
if (PFGetValue(variableName) === "Y") {
canArray.push(variableName);
}
canArray.join(", ");
}
return canArray[1];
}

Try
return eval('string output code');
So this would look like
return eval(array output);

Try this:
var dd_meg_1 = "M Energy 16";
var dd_meg_2 = "Ulra Energy";
var dd_meg_3 = "Another Option Here";
function canOrderMeg1() {
return ["dd_meg_1", "dd_meg_2", "dd_meg_3"];
}
for(let i = 0; i < canOrderMeg1().length; i++){
if(typeof canOrderMeg1()[i] !== "undefined") {
console.log(window[canOrderMeg1()[i]]);
}
}

Related

JS missing ) in parenthetical (line #88)

I'm writing a program in JS for checking equal angles in GeoGebra.
This is my first JS code, I used c# formerly for game programming.
The code is:
var names = ggbApplet.getAllObjectNames();
var lines = new Set();
var angles = new Set();
var groups = new Set();
for(var i=0; i<names.length; i++)
{
if(getObjectType(names[i].e)==="line")
{
lines.add(names[i]);
}
}
for(var i=0;i<lines.size;i++)
{
for(var j=0;j<i;j++)
{
var angle = new Angle(i,j);
angles.add(angle);
}
}
for(var i=0;i<angles.size;i++)
{
var thisVal = angles.get(i).value;
var placed = false;
for(var j=0;j<groups.size;j++)
{
if(groups.get(j).get(0).value===thisVal)
{
groups.get(j).add(angles.get(i));
placed = true;
}
}
if(!placed)
{
var newGroup = new Set();
newGroup.add(angles.get(i));
groups.add(newGroup);
}
}
for(var i=0;i<groups.size;i++)
{
var list="";
for(var j=0;j<groups.get(i).size;j++)
{
list = list+groups.get(i).get(j).name;
if(j != groups.get(i).size-1)
{
list = list+",";
}
}
var comm1 = "Checkbox[angle_{"+groups.get(i).get(0).value+"},{"+list+"}]";
ggbApplet.evalCommand(comm1);
var comm2 = "SetValue[angle_{"+groups.get(i).get(0).value+"}+,0]";
ggbApplet.evalCommand(comm2);
}
(function Angle (i, j)
{
this.lineA = lines.get(i);
this.lineB = lines.get(j);
this.name = "angleA_"+i+"B_"+j;
var comm3 = "angleA_"+i+"B_"+j+" = Angle["+this.lineA+","+this.lineB+"]";
ggbApplet.evalCommand(comm3);
var val = ggbApplet.getValue(this.name);
if(val>180)
{val = val-180}
this.value = val;
ggbApplet.setVisible(name,false)
});
function Set {
var elm;
this.elements=elm;
this.size=0;
}
Set.prototype.get = new function(index)
{
return this.elements[index];
}
Set.prototype.add = new function(object)
{
this.elements[this.size]=object;
this.size = this.size+1;
}
It turned out that GeoGebra does not recognize Sets so I tried to make a Set function.
Basically it collects all lines into a set, calculates the angles between them, groups them and makes checkboxes to trigger visuals.
the GeoGebra functions can be called via ggbApplet and the original Workspace commands via ggbApplet.evalCommand(String) and the Workspace commands I used are the basic Checkbox, SetValue and Angle commands.
The syntax for GeoGebra commands are:
Checkbox[ <Caption>, <List> ]
SetValue[ <Boolean|Checkbox>, <0|1> ]
Angle[ <Line>, <Line> ]
Thank you for your help!
In short, the syntax error you're running to is because of these lines of code:
function Set {
and after fixing this, new function(index) / new function(object) will also cause problems.
This isn't valid JS, you're likely looking for this:
function Set() {
this.elements = [];
this.size = 0;
}
Set.prototype.get = function(index) {
return this.elements[index];
};
Set.prototype.add = function(object) {
this.elements[this.size] = object;
this.size = this.size + 1;
};
Notice no new before each function as well.
I'm not sure what you're trying to accomplish by creating this Set object though - it looks like a wrapper for holding an array and its size, similar to how something might be implemented in C. In JavaScript, arrays can be mutated freely without worrying about memory.
Here's an untested refactor that removes the use of Set in favour of native JavaScript capabilities (mostly mutable arrays):
var names = ggbApplet.getAllObjectNames();
var lines = [];
var angles = [];
var groups = [];
for (var i = 0; i < names.length; i++) {
if (getObjectType(names[i].e) === "line") {
lines.push(names[i]);
}
}
for (var i = 0; i < lines.length; i++) {
for (var j = 0; j < i; j++) {
angles.push(new Angle(i, j));
}
}
for (var i = 0; i < angles.length; i++) {
var thisVal = angles[i].value;
var placed = false;
for (var j = 0; j < groups.length; j++) {
if (groups[j][0].value === thisVal) {
groups[j].push(angles[i]);
placed = true;
}
}
if (!placed) {
groups.push([angles[i]]);
}
}
for (var i = 0; i < groups.length; i++) {
var list = "";
for (var j = 0; j < groups[i].length; j++) {
list += groups[i][j].name;
if (j != groups[i].length - 1) {
list += ",";
}
}
var comm1 = "Checkbox[angle_{" + groups[i][0].value + "},{" + list + "}]";
ggbApplet.evalCommand(comm1);
var comm2 = "SetValue[angle_{" + groups[i][0].value + "}+,0]";
ggbApplet.evalCommand(comm2);
}
function Angle(i, j) {
this.name = "angleA_" + i + "B_" + j;
var comm3 = "angleA_" + i + "B_" + j + " = Angle[" + lines[i] + "," + lines[j] + "]";
ggbApplet.evalCommand(comm3);
var val = ggbApplet.getValue(this.name);
if (val > 180) {
val -= 180;
}
this.value = val;
ggbApplet.setVisible(name, false);
}
Hopefully this helps!
Your function definition is missing the parameter list after the function name.
Also, you're initializing the elements property to an undefined value. You need to initialize it to an empty array, so that the add method can set elements of it.
function Set() {
this.elements=[];
this.size=0;
}

Spliting String and getting appropriate value in JavaScript

I have a string where |||| means next to it is the directory. ||| means the user is allowed to access this directory and || means the files allocated to these users follow.
I need to find allocated file names of a specific user from this string. I have tried to split the string and assign values to an array but I am not able to get the result I'm looking for.
This is the string:
||||Root|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,||||1400842226669|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,||||1401191909489|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,LimitTest_20140528164643.xlsx,
And here is my attempt:
function getData() {
var user = 'km11285c';
var value = "||||Root|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,||||1400842226669|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,||||1401191909489|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,LimitTest_20140528164643.xlsx,";
var users = null;
var files = null;
var Dir = value.split("||||");
var arrayLength = Dir.length;
for (var i = 0; i < arrayLength; i++) {
users = Dir[i].split("|||");
}
return users;
}
console.log(getData());
and the jsFiddle
I changed your jsfiddle example a bit so maybe you need to change the code here and there, but something like this should work:
function buildTree(data) {
var tree = [];
var dirs = data.split("||||");
// Remove the first entry in the array, since it should be empty.
dirs.splice(0, 1);
for (var i = 0; i < dirs.length; ++i) {
var tempArray = dirs[i].split("|||");
var dirName = tempArray[0];
var usersAndFiles = tempArray[1];
tempArray = usersAndFiles.split("||");
var users = tempArray[0];
var files = tempArray[1];
var treeDir = { name: dirName };
treeDir.users = users.split(",");
treeDir.files = files.split(",");
tree.push(treeDir);
}
return tree;
}
function getData() {
var user = 'km11285c';
var value="||||Root|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,||||1400842226669|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,||||1401191909489|||adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,km11285c,km61052,km61639c,adil001,kl04707c,km47389,km58184,km61052,kq61023c,||LimitTest_20140528164643.xlsx,testTask2_20140528140033.xlsx,testTask1_20140528135944.xlsx,testTask2_20140528140033.xlsx,LimitTest_20140528164643.xlsx,";
var tree = buildTree(value);
for (var i = 0; i < tree.length; ++i) {
var dir = tree[i];
if (dir.users.indexOf(user) >= 0) {
console.log("User '" + user + "' has access to directory '" + dir.name + "', which contains these files: " + dir.files.join(","));
}
}
}
getData();

generate list of variables from a FOR loop

var select = [];
for (var i = 0; i < nameslots; i += 1) {
select[i] = this.value;
}
This is an extract of my code. I want to generate a list of variables (select1, select2, etc. depending on the length of nameslots in the for.
This doesn't seem to be working. How can I achieve this? If you require the full code I can post it.
EDIT: full code for this specific function.
//name and time slots
function gennametime() {
document.getElementById('slots').innerHTML = '';
var namelist = editnamebox.children, slotnameHtml = '', optionlist;
nameslots = document.getElementById('setpresentslots').value;
for (var f = 0; f < namelist.length; f += 1) {
slotnameHtml += '<option>'
+ namelist[f].children[0].value
+ '</option>';
};
var select = [];
for (var i = 0; i < nameslots; i += 1) {
var slotname = document.createElement('select'),
slottime = document.createElement('select'),
slotlist = document.createElement('li');
slotname.id = 'personname' + i;
slottime.id = 'persontime' + i;
slottime.className = 'persontime';
slotname.innerHTML = slotnameHtml;
slottime.innerHTML = '<optgroup><option value="1">00:01</option><option value="2">00:02</option><option value="3">00:03</option><option value="4">00:04</option><option value="5">00:05</option><option value="6">00:06</option><option value="7">00:07</option><option value="8">00:08</option><option value="9">00:09</option><option value="10">00:10</option><option value="15">00:15</option><option value="20">00:20</option><option value="25">00:25</option><option value="30">00:30</option><option value="35">00:35</option><option value="40">00:40</option><option value="45">00:45</option><option value="50">00:50</option><option value="55">00:55</option><option value="60">1:00</option><option value="75">1:15</option><option value="90">1:30</option><option value="105">1:45</option><option value="120">2:00</option></optgroup>';
slotlist.appendChild(slotname);
slotlist.appendChild(slottime);
document.getElementById('slots').appendChild(slotlist);
(function (slottime) {
slottime.addEventListener("change", function () {
select[i] = this.value;
});
})(slottime);
}
}
You'll have to close in the iterator as well in that IIFE
(function (slottime, j) {
slottime.addEventListener("change", function () {
select[j] = this.value;
});
})(slottime, i);
and it's only updated when the element actually change
The cool thing about JavaScript arrays is that you can add things to them after the fact.
var select = [];
for(var i = 0; i < nameSlots; i++) {
var newValue = this.value;
// Push appends the new value to the end of the array.
select.push(newValue);
}

How to change the flow of execution and function call in this Google Apps Script?

I have a main function generatePersonDatasheet(theses) and I have a handler function submit(e) (the handler is in other function called showList()).
In the main function, I can call the handler function this way:
if (theses == 1){
Logger.log("going to showList() ");
return showList();
If I drop de return in the line return showList(); the UI of showList() opens and closes at a fraction of second, not allowing the user choose the items. If I put this return, after the handler function submit(e) is closed, the code in my main function doesn't run the next line after the if block:
if (theses == 1){
Logger.log("going to showList() ");
return showList();
}
showURL(docName, link); // Shows document name and link in UI
How could I fix that? How could I got the main function to runs its lines after the if (theses == 1) block? I didn't want to repeat the code in the handler function because it's bigger than the line showURL(docName, link); in the above sample.
This is the called functions:
var fact_list = [ ["Kennedy Inauguration", "politics", "tZwnNdFNkNklYc3pVUzZINUV4eUtWVWFSVEf"], ["Pericles’ Funeral Oration", "politics", "sdgrewaNkNklYc3pVUzZINUV4eUtW345ufaZ"], ["The Pleasure of Books", "culture", "1234rFszdgrfYc3pVUzZINUV4eU43usacd"], ["I Am The First Accused (Nelson Mandela)", "law", "34rsgadOsidjSZIswjadi95uydnfklsdks"] ];
function showList() {
Logger.log("running showList ");
var mydoc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var panel = app.createVerticalPanel().setId('panel');
// Store the number of items in the array (fact_list)
Logger.log("fact_list.length " + fact_list.length);
panel.add(app.createHidden('checkbox_total', fact_list.length));
// add 1 checkbox + 1 hidden field per item
for(var i = 0; i < fact_list.length; i++){
Logger.log("checkbox_isChecked_"+i + " = " + fact_list[i][0]);
Logger.log("checkbox_value_"+i + " = " + fact_list[i]);
var checkbox = app.createCheckBox().setName('checkbox_isChecked_'+i).setText(fact_list[i][0]);
var hidden = app.createHidden('checkbox_value_'+i, fact_list[i]);
panel.add(checkbox).add(hidden);
}
var handler = app.createServerHandler('submit').addCallbackElement(panel);
panel.add(app.createButton('Submit', handler));
app.add(panel);
mydoc.show(app);
}
function submit(e){
Logger.log("running submit(e)");
var numberOfItems = e.parameter.checkbox_total;
var itemsSelected = [];
// for each item, if it is checked / selected, add it to itemsSelected
for(var i = 0; i < numberOfItems; i++){
if(e.parameter['checkbox_isChecked_'+i] == 'true'){
itemsSelected.push(e.parameter['checkbox_value_'+i]);
}
}
var app = UiApp.getActiveApplication();
Logger.log("itemsSelected = " + itemsSelected);
ScriptProperties.setProperties({'theses': itemsSelected}, true);
var thesesArrays = ScriptProperties.getProperty('theses');
Logger.log("thesesArrays = " + thesesArrays);// to see targetDoc's content
for (var i = 0; i < thesesArrays.lenght; i++){
var thesesId = ScriptProperties.getProperty('theses')[i][2];
var thesesType = ScriptProperties.getProperty('theses')[i][1];
importTheses(target, thesesId, thesesType);
}
app.close();
return app;
}
function importTheses(targetDocId, thesesId, thesesType) { // adapted from Serge insas
Logger.log("running importTheses() ");
var targetDoc = DocumentApp.openById(targetDocId);
var targetDocParagraphs = targetDoc.getParagraphs();
var targetDocElements = targetDocParagraphs.getNumChildren();
var thesesDoc = DocumentApp.openById(thesesId);
var thesesParagraphs = thesesDoc.getParagraphs();
var thesesElements = thesesDoc.getNumChildren();
var eltargetDoc=[];
var elTheses=[];
for( var j = 0; j < targetDocElements; ++j ) {
var targetDocElement = targetDoc.getChild(j);
// Logger.log(j + " : " + type);// to see targetDoc's content
eltargetDoc[j]=targetDocElement.getText();
if(el[j]== thesesType){
for( var k = 0; k < thesesParagraphs-1; ++k ) {
var thesesElement = thesesDoc.getChild(k);
elTheses[k] = thesesDoc.getText();
targetDoc.insertParagraph(j, elTheses[k]);
}
}
}
}
Please have a look at this worflow, wouldn't it be more easy ?
(check the log to confirm the last function was called)
note : I didn't use scriptProperties as it was not necessary anymore since factList is a global variable in your example... and I simplified the importTheses function for this test since I had no docs to use ;-)
var fact_list = [["Kennedy Inauguration", "politics", "tZwnNdFNkNklYc3pVUzZINUV4eUtWVWFSVEf"], ["Pericles Funeral Oration", "politics", "sdgrewaNkNklYc3pVUzZINUV4eUtW345ufaZ"], ["The Pleasure of Books", "culture", "1234rFszdgrfYc3pVUzZINUV4eU43usacd"], ["I Am The First Accused (Nelson Mandela)", "law", "34rsgadOsidjSZIswjadi95uydnfklsdks"]];
function showList() {
var mydoc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var panel = app.createVerticalPanel().setId('panel');
// Store the number of items in the array (fact_list)
panel.add(app.createHidden('checkbox_total', fact_list.length));
// add 1 checkbox + 1 hidden field per item
for(var i = 0; i < fact_list.length; i++){
var checkbox = app.createCheckBox().setName('checkbox_isChecked_'+i).setText(fact_list[i][0]);
panel.add(checkbox);
}
var handler = app.createServerHandler('submit').addCallbackElement(panel);
panel.add(app.createButton('Submit', handler));
app.add(panel);
mydoc.show(app);
}
function submit(e){
var numberOfItems = Number(e.parameter.checkbox_total);
var thesesArrays = [];
for(var i = 0; i < numberOfItems; i++){
if(e.parameter['checkbox_isChecked_'+i] == 'true'){
thesesArrays.push(fact_list[i]);
}
}
Logger.log(thesesArrays);
var target = 'target doc';
for (var i = 0; i < thesesArrays.length; i++){
var thesesId = thesesArrays[i][2];
var thesesType = thesesArrays[i][1];
importTheses(target, thesesId, thesesType);
}
// showURL(docName, link); /
return UiApp.getActiveApplication().close();
}
function importTheses(targetDocId, thesesId, thesesType) { // adapted from Serge insas
Logger.log(targetDocId+' '+thesesId+' '+thesesType);
}

javascript, .split(), implement additional variable

I found a code for city,state dropdown menu. It works flawlessly, but I am implementing additional feature by adding a US State to the following code:
//countries array
var countries = Object();
countries['Africa'] = '|Algeria|Angola|Benin';
//state array
var city_states = Object();
city_states['United States'] = '|Washington DC||Alabama|Alaska';
this is an array for US Cities, but I want to add a State abbreviation like so: DC, AL, AK and so on to be sent to the menu such as this:
function setRegions()
{
for (region in countries)
document.write('<option value="' + region + '">' + region + '</option>');
}
function set_country(oRegionSel, oCountrySel, oCity_StateSel)
{
var countryArr;
oCountrySel.length = 0;
oCity_StateSel.length = 0;
var region = oRegionSel.options[oRegionSel.selectedIndex].text;
if (countries[region])
{
oCountrySel.disabled = false;
oCity_StateSel.disabled = true;
oCountrySel.options[0] = new Option('SELECT COUNTRY','');
countryArr = countries[region].split('|');
for (var i = 0; i < countryArr.length; i++)
oCountrySel.options[i + 1] = new Option(countryArr[i], countryArr[i]);
document.getElementById('txtregion').innerHTML = region;
document.getElementById('txtplacename').innerHTML = '';
}
else oCountrySel.disabled = true;
}
function set_city_state(oCountrySel, oCity_StateSel)
{
var city_stateArr;
oCity_StateSel.length = 0;
var country = oCountrySel.options[oCountrySel.selectedIndex].text;
if (city_states[country])
{
oCity_StateSel.disabled = false;
oCity_StateSel.options[0] = new Option('SELECT NEAREST DIVISION','');
city_stateArr = city_states[country].split('|');
for (var i = 0; i < city_stateArr.length; i++)
oCity_StateSel.options[i+1] = new Option(city_stateArr[i],city_stateArr[i]);
document.getElementById('txtplacename').innerHTML = country;
}
else oCity_StateSel.disabled = true;
}
function print_city_state(oCountrySel, oCity_StateSel)
{
var country = oCountrySel.options[oCountrySel.selectedIndex].text;
var city_state = oCity_StateSel.options[oCity_StateSel.selectedIndex].text;
if (city_state && city_states[country].indexOf(city_state) != -1)
document.getElementById('txtplacename').innerHTML = city_state + ', ' + country;
else document.getElementById('txtplacename').innerHTML = country;
}
I was thinking adding an additional array of State abbreviations, but I think adding a simple state abbreviation to the already built array would do just fine by adding another value in the setregions() and having + abbreviation + instead of + region +. Any ideas how to implement it? -thank you.
If you have an array of States (objects) rather than an array of Strings you could do something like this:
function State(longName, shortName) {
this.longName = longName;
this.shortName = shortName;
}
I don't know what the abbreviations are, but store them like this in your array
var cityStates = "State:Abbrev|Washington DC:WDC|ETC:etc"
var stateNames = cityStates.split("|");
var states = new Array(stateNames.length);
for (i=0; i<states.length; i++)
var longName = stateNames[i].split(":")[0];
var shortName = stateNames[i].split(":")[1];
states[i] = new State(longName,shortName);
}
That would give you a new array "states" with 50 state objects, each which could be called like this:
states[0] //(returns a State object at index 0)
states[0].longName //(returns the long name)
states[0].shortName //(returns the abbreviated name)

Categories