Dynamic dictionary using Javascript from two sources - javascript

I'm new to JavaScript, and I think at this point I may have bit off more than I could chew. Essentially, I'm trying to make a dictionary (which will eventually be serialized to JSON, if that's relevant) that allows the user to define any number of entries and set both the key and value as they wish. I'm up for another implementation ideas, but this is how I've tried to solve it so far.
I have a button that calls the following code, which is mimicked exactly for newVariableDescription class. This creates the text input boxes on the web form.
var nameElement = document.createElement("input");
nameElement.type = "text";
nameElement.className = "newVariableName";
var nameDiv = document.createElement("div");
nameDiv.type = "div";
nameDiv.appendChild(nameElement);
var newVariableNamesDiv = document.getElementById("newVariableNamesDiv");
newVariableNamesDiv.appendChild(nameDiv);
var descriptionElement = document.createElement("input");
descriptionElement.type = "text";
descriptionElement.className = "newVariableDescription";
var descriptionDiv = document.createElement("div");
descriptionDiv.type = "div";
descriptionDiv.appendChild(descriptionElement);
var newVariableDescriptionsDiv = document.getElementById("newVariableDescriptionsDiv");
newVariableDescriptionsDiv.appendChild(descriptionDiv);
Now, this part works. I get all of the text boxes showing up just like I want, and can type into them. However, I can't figure out how to dynamically get access to this list AND pair them together.
This thread is very similar to what I want to do: dynamic dictionary using javascript
But I can't figure out how to get this code to do what I want:
var dictionary = {};
$('.newVariableName).each(function (index) {
dictionary['['+index+'].Key'] = $(this).val();
dictionary['['+index+'].Value'] = //access corresponding newVariableDescription here
});
I can obviously create a second loop with the other class (newVariableDescription), but that won't tie them together properly. I could store each of them in their own separate lists, and then combine those two lists into a dictionary, but I'm concerned about order remaining consistent and that's not an elegant solution.
Thanks in advance for any help.

If i understand right you want something like this with :eq selector
var dictionary = {};
$('.newVariableName').each(function (index) {
dictionary['['+index+'].Key'] = $(this).val();
dictionary['['+index+'].Value'] = $('.newVariableDescription:eq('+index+')').val();
});

Related

I used js to create my command syntax, now how can I use it?

I have a Google Sheet with .gs script that is successfully generating dynamicnewRichTextValue() parameters which are meant to be injected into a Sheet cell that will contain multiple lines of text each with their own URL. I do not know all of the parameters in advance (might be one text and one link, or two each, or more) which is why I am dynamically generating the parameters.
Let's say the end-state should be this (in this case there are only two line items, but there could be more or less:
var RichTextValue=SpreadsheetApp.newRichTextValue()
.setText("mailto:fred#abcdef.com,mailto:jim#abcdef.com")
.setLinkUrl(0,6,"mailto:fred#abcdef.com")
.setLinkUrl(7,19,"mailto:jim#abcdef.com")
.build();
In my script I don't know how many "setText" parameters or "setLinkUrl" statements I will need to generate, so I am doing it dynamically.
This is simple to handle for "setText" because I can just pass a single variable constructed during an earlier loop that builds the "setText" parameters. Let's call that variable setTextContent, and it works like this:
var RichTextValue=SpreadsheetApp.newRichTextValue()
.setText(setTextContent)
So up to this point, everything is great. The problem is that I have another variable that generates the URL portion of the newrichtextvalue() parameters up to the ".build();" statement. So let's call that variable setUrlContent and it is built in an earlier loop and contains the string for the rest of the statement:
.setLinkURL(0,22,"mailto:fred#abcdef.com").setLinkURL(23,44,"mailto:jim#abcdef.com")
I am stumped trying to figure out how to attach it to the earlier bit. I feel like this is something simple I am forgetting. But I can't find it after much research. How do I hook up setUrlContent to the code above so that the command executes? I want to attach the bits above and get back to assigning it all to a variable I can put into a cell:
var emailCell=SpreadsheetApp.newRichTextValue()
.setText("mailto:fred#abcdef.com,mailto:jim#abcdef.com") // I can dynamically create up to here
.setLinkUrl(0,6,"mailto:fred#abcdef.com") // ...but these last couple lines are
.setLinkUrl(7,19,"mailto:jim#abcdef.com") // stuck in a string variable.
.build();
sheet.getRange(1,1,1,1).setRichTextValue(emailCell)
Thanks!
I believe your goal and situation as follows.
You want to use your script by dynamically changing the number of emails.
Modification points:
When your following script is run, I think that the links are reflected to mailto and fred#abcdef..
var emailCell=SpreadsheetApp.newRichTextValue()
.setText("mailto:fred#abcdef.com,mailto:jim#abcdef.com")
.setLinkUrl(0,6,"mailto:fred#abcdef.com")
.setLinkUrl(7,19,"mailto:jim#abcdef.com")
.build();
sheet.getRange(1,1,1,1).setRichTextValue(emailCell)
I thought that you might have wanted the linked email addresses like below.
fred#abcdef.com has the link of mailto:fred#abcdef.com.
jim#abcdef.com has the link of mailto:jim#abcdef.com.
In this answer, I would like to propose the modified script for above direction.
Modified script:
var inputText = "mailto:fred#abcdef.com,mailto:jim#abcdef.com"; // This is your sample text value.
var ar = inputText.split(",").map(e => {
var v = e.trim();
return [v.split(":")[1], v];
});
var text = ar.map(([e]) => e).join(",");
var emailCell = SpreadsheetApp.newRichTextValue().setText(text);
var start = 0;
ar.forEach(([t, u], i) => {
var len = t.length;
emailCell.setLinkUrl(start, start + len, u);
start += len + 1;
});
SpreadsheetApp.getActiveSheet().getRange(1,1,1,1).setRichTextValue(emailCell.build());
In this modification, inputText is splitted to the hyperlink and the text (for example, when your sample value is used, it's fred#abcdef.com and mailto:fred#abcdef.com.), and the text including the hyperlink are put to the cell.
In this case, for example, even when var inputText = "mailto:fred#abcdef.com,mailto:jim#abcdef.com" is modified to var inputText = "mailto:fred#abcdef.com" and var inputText = "mailto:fred#abcdef.com,mailto:jim#abcdef.com,mailto:sample#abcdef.com", each hyperlink are reflected to each text.
Note:
When you want to the hyperlink of mailto:fred#abcdef.com to the text of mailto:fred#abcdef.com, you can also use the following modified script.
var inputText = "mailto:fred#abcdef.com,mailto:jim#abcdef.com"; // This is your sample text value.
var ar = inputText.split(",").map(e => e.trim());
var emailCell = SpreadsheetApp.newRichTextValue().setText(inputText);
var start = 0;
ar.forEach((t, i) => {
var len = t.length;
emailCell.setLinkUrl(start, start + len, t);
start += len + 1;
});
SpreadsheetApp.getActiveSheet().getRange(1,1,1,1).setRichTextValue(emailCell.build());
References:
newRichTextValue()
Class RichTextValueBuilder
Class RichTextValue

How can I get a value from user and use it in Javascript

I am trying to make a quiz game and want to allow an user to choose game difficulty. I have a JSON list, which includes questions.
var easy = '[{"eser":"Question1","yazar":"Answer1"},{"eser":"Question2","yazar":"Answer2"}]';
var hard = '[{"eser":"Question3","yazar":"Answer3"},{"eser":"Question4","yazar":"Answer4"}]';
and I parse it like below
difficulty = JSON.parse(easy);
var count = Object.keys(difficulty).length;
When the game opens, it shows a popup which wants from user to select difficulty. Basically when user click Hard, I want to catch it and change the code above as difficulty = JSON.parse(hard);
HTML code is here
<div class="button_easy">Easy</div>
<div class="button_hard">Hard</div>
Thanks
Don't use separate variables, use an object whose keys correspond to something in the element they select.
const questions = {
easy: [{"eser":"Question1","yazar":"Answer1"},{"eser":"Question2","yazar":"Answer2"}],
hard: [{"eser":"Question3","yazar":"Answer3"},{"eser":"Question4","yazar":"Answer4"}]
};
The HTML can be like:
<div class="difficulty" data-level="easy">Easy</div>
<div class="difficulty" data-level="hard">Hard</div>
And the JS would be:
let chosen_questions;
document.querySelector(".difficulty").forEach(b => b.addEventListener("click", function() {
let level = this.dataset.level;
chosen_questions = questions[level];
}));
You can do it with eval function (error handling is omitted here if there is no such variable named the string represented by user_choice):
var difficulty = JSON.parse(eval(user_choice))
But I think it might be better to put those two lists inside a dictionary like this:
var difficulty_dic = {
'easy': easy,
'hard': hard
}
And later you can do something like:
var difficulty = JSON.parse(difficulty_dic[user_choice])

I want to create a dropdown list with the data available on another sheet

I want to create a dropdown list with the data available on another sheet
function dropOrderStatus() {
var cell = SpreadsheetApp.getActive().getRange('B12');
var orderStatusRange = SpreadsheetApp.openById("1sO_M9H7CrCevNrKCr0eimxb9lmY458NeyNHTf8RpS60").getNamedRanges('countryList');
var orderStatus = SpreadsheetApp.newDataValidation().requireValueInRange(orderStatusRange).build();
cell.setDataValidation(countryList);
}
You can't use getNamedRanges that way. You get all of the named ranges and then iterate over them. Then you can assign the rule.
function dropOrderStatus() {
var cell = SpreadsheetApp.getActive().getRange('B12');
var orderStatusRange = SpreadsheetApp.openById("1sO_M9H7CrCevNrKCr0eimxb9lmY458NeyNHTf8RpS60").getNamedRanges();
var namedRanges = [];
for(var i = 0; i < orderStatusRange.length; i++) {
namedRanges.push(orderStatusRange[i].getRange());
}
//I have no idea what your named ranges look like so you will need to modify this.
//It only takes the first named ranged in the array of named ranges
//If you want a dropdown for this you need to set it up differently
var rule = SpreadsheetApp.newDataValidation().requireValueInRange(namedRanges[0]).build();
cell.setDataValidation(rule);
}
As a sidenote, I published a free add-on in the web store that builds these kind of dropdowns, and I would love feedback. I don't know what the rules are about linking to things like that, but you can find it easily by searching 'Multi Dropdowns'

Is there an easier method to concatenate variables using JavaScript?

I'm currently doing this:
var 1 = "http://www";
var 2 = ".google.";
var 3 = "com/";
then concatenating them together like this
var link = 1+2+3;
Is there an easier and more proficient way of doing this?
I don't know what would be much easier than simple concatenation like you show, but you could put them in an Array and join it together.
(I fixed your variable names to make them valid.)
var first = "http://www";
var second = ".google.";
var third = "com/";
var link = [first, second, third].join("");
Or you could use the .concat() method.
var link = first.concat(second, third);
But both of these are longer than your original so I don't know if that's what you want.

Is it possible to link container to other one?

I have an array of data. I have put this data on my site in different places over different attributes, how innerHTML value placeholder etc.
Is it possible to link this values with the array from where I can take data? So that when I change the data in array, it going automatic changed on the site?
Also I try to show how I did it mean:
var test = Array();
test['place1'] = 'NY';
var myspan = document.createElement('span');
myspan.innerHTML = test['place1'];
On some event the value of test['place1'] is changed to 'LA', and at the same moment the value of myspan.innerHTML must be changed too.
Native JS only please.
This needs to be manually managed. A simple solution would be something like this:
function Place(container, initVal) {
this.container = container ? container : {};
this.set(initVal);
}
Place.prototype.place = "";
Place.prototype.get = function() {
return this.place;
}
Place.prototype.set = function(val) {
this.place = val;
this.container.innerHTML = val;
}
var test = {}; // object
test['place1'] = new Place(document.createElement('span'), "NY")
test['place1'].set('New Value');
This is not a full-feature solution, but gives you an idea of the coordination that needs to take place.
If you're only supporting modern browsers, then the syntax can be cleaned up a bit by using getters/setters.
In the future, you'll be able to use Proxy, which will make it even easier and cleaner.
There is no native way to bind an attribute of an HTML element to the values of an array, but you aren't actually using an array; you're using an object, and it is a simple matter to define special features on an object. For example:
First, define your object:
function boundArray(){
this._bindings = {};
this.setBinding = function(key,element){
this._bindings[key] = element;
};
this.setValue = function(key,value){
this[key] = value;
if(this._bindings[key]){
this._bindings[key].innerHTML = value;
}
}
}
Then use it in your code:
// create a new instance of the boundArray
var test = new boundArray();
// create the HTML element to use, and add it to the DOM
var myspan = document.createElement('span');
document.body.appendChild(myspan);
// bind the HTML element to the required key in the boundArray
test.setBinding('place1',myspan);
// Now every time you set that key on the boundArray (using setValue), it will also change the innerHTML field on the element
test.setValue('place1','NY');
// You can access your information from the boundArray in the usual ways:
var somevar = test.place1;
var anothervar = test['place1'];
What you are talking about is an MVVM solution. Most MVVM JavaScript solutions uses some object that represents an observable, which is a field within the object. When the value in the object changes, the observable lets the framework know to update the DOM. It also listens to the DOM for change events, and updates the object in reverse. For arrays, it's a similar process: it listens for adds or removes of the array, and updates the UI accordingly.
As #MCL points out in the comments on this post below, there is a way to watch changes to an object, and it isn't overly difficult to generically attach to an element on the DOM. However, There are a lot of good frameworks out there that make this REALLY easy, so that may be something to consider.

Categories

Resources