How could I set the value of an item in a json object by passing in the name of it via a parameter to a function?
eg:
this.loadStates = function() {
that.setStateIfExists('inStock', true);
}
this.setStateIfExists = function (param, option) {
// i'd like this to be 'that.selectedFinderOptions.inStock = option'
that.selectedFinderOptions.param = option;
}
Is this even possible or should I be thinking of doing this differently?
Use an indexer:
that.selectedFinderOptions[param] = option;
Your use of the phrase "JSON object" has us a bit confused. JSON is a flattened, string representation of the serialization of one or more javascript objects. So, you don't do anything dynamically with a piece of JSON. It's just a string.
If, what you mean is that you have a javascript object instead, then we can discuss options. For a javascript object, you have a couple choices. First off, you can just use an attribute on that object and have it's value reflect what you want:
var myObj = {};
myObj.inStock = true;
Then, anyone can access myObj.inStock and get the current value of that property.
If what, you want is for the value of instock to be computed by a function rather than be static assigned to the object and you want your code to work across all browsers, then you would have to change the way you access that to be via a method call:
var myObj = {};
myObj.getInStockValue = function() {
// execute whatever code you want here to
// compute the desired value and return it when done
};
Then, anyone can access it with myObj.getInStockValue().
In your specific example, you could change this:
this.setStateIfExists = function (param, option) {
// i'd like this to be 'that.selectedFinderOptions.inStock = option'
that.selectedFinderOptions.param = option;
}
to this:
this.setStateIfExists = function (param, option) {
// i'd like this to be 'that.selectedFinderOptions.inStock = option'
that.selectedFinderOptions[param] = option;
}
When the parameter is dynamic and contained in a variable, you use the [param] syntax instead of the .param syntax. They both do the same thing logically, but the [param] syntax is the only one that works when the name of the thing you want to look up is in a variable.
Related
I'm a big noob at JS,so if my question is hard to understand then sorryđŸ˜‚.
I'm writing a program in JS(Electron) that provides a user interface for another program I made in C++, so I'm basically rewriting it in JavaScript.
I want to use this JSON variable(or whatever it's called) in my code.
var ShowSecondsInSystemClock = '{"name":"ShowSecondsInSystemClock","Description":"Patches the System Tray clock to show seconds","ExplorerRestartRequired":"true","category":"UI-Tweaks","badges":"UITweaks"}'
Then I would like to use this function where the parameter of the function "ShowSecondsInSystemClock" is.
function TweakParser(TweakName, NeeddedReturn) {
if (NeeddedReturn == "Description") {
//I'm trying to use TweakName as the parameter of parse(),but it only
//accepts the name of the Tweak directly
var NeeddedTweakInfo = JSON.parse(TweakName)
return NeeddedTweakInfo.Description
}
}
Because there will be many Tweaks, the usecase of this particular function is for example
//I use a non-existing tweak here for the example
TweakParser("RemoveArrowsFromShortcut","Description")
What I want TweakParser to do now is use RemoveArrowsFromShortcut as the parameter of JSON.parse() but it only accept the name of the JSON variable directly and when I input the name of the first parameter of the TweakParser() function it gives me an error, because the parameter(a variable) itself is not a JSON variable (or whatever it's called like).
So my question to you is:
How can I use the string that the first parameter of TweakParser() contains as a parameter for the JSON.parse() function?
You need to create mapping
like a schema 'key': variable
example:
{
'RemoveArrowsFromShortcut': ShowSecondsInSystemClock
}
Full example:
var ShowSecondsInSystemClock = '{"name":"ShowSecondsInSystemClock","Description":"Patches the System Tray clock to show seconds","ExplorerRestartRequired":"true","category":"UI-Tweaks","badges":"UITweaks"}'
var mapping = {
RemoveArrowsFromShortcut: ShowSecondsInSystemClock
};
function TweakParser(TweakName, NeeddedReturn) {
if (NeeddedReturn == "Description") {
var NeeddedTweakInfo = JSON.parse(mapping[TweakName]); // PAY ATTENTION HERE
return NeeddedTweakInfo.Description
}
}
var result = TweakParser("RemoveArrowsFromShortcut","Description")
console.log('result', result)
I'm struggling to dynamically convert a set of inputs into a multi-dimensional object for passing in an ajax call.
Assume I have a Person, with multiple Addresses.
My fields currently look like this:
<input name='Person[name]' value='Bradley'/>
<input name='Person[addresses][home]' value='123 Anywhere Drive.'/>
<input name='Person[addresses][work]' value='456 anywhere Road.'/>
How would one convert my fields into ab object that looks like this:
Person :
{
name: 'Bradley',
addresses:
{
home: '123 Anywhere Drive.',
work: '456 anywhere Road.'
}
}
I need to do this dynamically (function needs to work regardless of the inputs provided) and work at N-depth.
(Note: jQuery available).
http://jsfiddle.net/w4Wqh/1/
Honestly I think there's a way to do this in a regex.. but I couldn't figure it out. So, it's a bit of ugly string manipulation. Either way, this should get you on the right track I think:
function serialize () {
var serialized = {};
$("[name]").each(function () {
var name = $(this).attr('name');
var value = $(this).val();
var nameBits = name.split('[');
var previousRef = serialized;
for(var i = 0, l = nameBits.length; i < l; i++) {
var nameBit = nameBits[i].replace(']', '');
if(!previousRef[nameBit]) {
previousRef[nameBit] = {};
}
if(i != nameBits.length - 1) {
previousRef = previousRef[nameBit];
} else if(i == nameBits.length - 1) {
previousRef[nameBit] = value;
}
}
});
return serialized;
}
console.log(serialize());
Quick explanation. This just grabs anything with a 'name' attribute, and then iterates over them. For each iteration, it grabs the name and splits it on '['. This gets you basically how far into the object you need to put things. So, for Person[addresses][work], you would get Person, addresses], work].
Then, there's the tricky part. Since objects are always passed around by reference, we can see if the serialized variable has 'Person' in it. If not, it adds it, and sets the value to an empty object.. which is generic enough to be used for storing more things, or replaced if necessary. If there are no more levels that we need to go through, it just takes the value of the element and assigns it to the reference it has. Otherwise, the code grabs a reference to whatever it just made, and loops again, performing the same operation. So, for Person[addresses][work]..
Does serialized.Person exist? No. Setting serialized.Person to {}. This is not the end of the loop, store reference to serialized.Person as previousRef.
Does previousRef.addresses exist? (serialized.Person.addresses) No. Setting previousRef.addresses to {}. This is not the end of the loop, store reference to previousRef.addresses as previousRef.
Does previousRef.work exist? (serialized.Person.addresses.work) No. Setting previousRef.work to {}. Wait. This is the end of the loop. Setting previousRef.work to the value in the element.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dynamic object property name
I have an object like this
var localAppConfig = {
wallet:0,
paySomeone:0,
payBills:0,
accounts:0,
moveMoney:0,
alerts:0,
offers:0,
checkIn:0
};
I want to set value 1 for particular elements within this localAppConfig
Which element needs to be set is retrieved from the json - which arrives from the server.
say, I want to set value = 1 for wallet, paySomeone, payBills, alerts, offers, checkIn
These are retirved from the json like
for(var i=0;i<len;i++){
var name = list[i].handle;
var accessor = eval('localAppConfig.'+name);
eval('localAppConfig.'+name)=1;
}
var name contains name of the element and I am able to access its value correctly,
How can I set the value using javascript?
I tried accessor=1 but its not working.
Thanks :)
Anyhow: try this on for size:
localAppConfig[name] = 1;//where name is a variable of choice, it's value will be used as the propertyname
And again:
-When all you have is the eval hammer, everything looks like your thumb.
–Brendan Eich in response to: we should encourage use of eval() rather than the Function constructor for dynamic creation of functions.
But why use a list of the properties? you might as well use a for...in loop: in case of objects, like yours, it's perfectly all right. As long as you check .hasOwnProperty, too:
for (var prop in localAppConfig)
{
if (localAppConfig.hasOwnProperty(name))
{
//set, delete... do whatever
}
}
You should do this instead:
var accessor = localAppConfig[name];
localAppConfig[name] = 1;
Try localAppConfig[name] = 1;
It's just a javascript object, no need to use eval() on it.
Don't use eval(). You can add a property by referencing the index of that value within your object. If it doesn't exist then it will be created, otherwise the value will be overridden.
Try the following instead:
// localAppConfig[list[i].handle] = 1;
for(var i=0;i<len;i++){
localAppConfig[list[i].handle] = 1;
}
Or if you intend to reference the variable in another place then set a variable with the value of list[i].handle:
for(var i=0;i<len;i++){
var name = list[i].handle;
var accessor = localAppConfig[name];
localAppConfig[name] = 1;
}
A simple question I'm sure, but I can't figure it out.
I have some JSON returned from the server
while ($Row = mysql_fetch_array($params))
{
$jsondata[]= array('adc'=>$Row["adc"],
'adSNU'=>$Row["adSNU"],
'adname'=>$Row["adname"],
'adcl'=>$Row["adcl"],
'adt'=>$Row["adt"]);
};
echo json_encode(array("Ships" => $jsondata));
...which I use on the client side in an ajax call. It should be noted that the JSON is parsed into a globally declared object so to be available later, and that I've assumed that you know that I formated the ajax call properly...
if (ajaxRequest.readyState==4 && ajaxRequest.status==200 || ajaxRequest.status==0)
{
WShipsObject = JSON.parse(ajaxRequest.responseText);
var eeWShips = document.getElementById("eeWShipsContainer");
for (i=0;i<WShipsObject.Ships.length;i++)
{
newElement = WShipsObject.Ships;
newWShip = document.createElement("div");
newWShip.id = newElement[i].adSNU;
newWShip.class = newElement[i].adc;
eeWShips.appendChild(newWShip);
} // end for
}// If
You can see for example here that I've created HTML DIV elements inside a parent div with each new div having an id and a class. You will note also that I haven't used all the data returned in the object...
I use JQuery to handle the click on the object, and here is my problem, what I want to use is the id from the element to return another value, say for example adt value from the JSON at the same index. The trouble is that at the click event I no longer know the index because it is way after the element was created. ie I'm no longer in the forloop.
So how do I do this?
Here's what I tried, but I think I'm up the wrong tree... the .inArray() returns minus 1 in both test cases. Remember the object is globally available...
$(".wShip").click(function(){
var test1 = $.inArray(this.id, newElement.test);
var test2 = $.inArray(this.id, WShipsObject);
//alert(test1+"\n"+test2+"\n"+this.id);
});
For one you can simply use the ID attribute of the DIV to store a unique string, in your case it could be the index.
We do similar things in Google Closure / Javascript and if you wire up the event in the loop that you are creating the DIV in you can pass in a reference to the "current" object.
The later is the better / cleaner solution.
$(".wShip").click(function(){
var id = $(this).id;
var result;
WShipsObject.Ships.each(function(data) {
if(data.adSNU == id) {
result = data;
}
});
console.log(result);
}
I could not find a way of finding the index as asked, but I created a variation on the answer by Devraj.
In the solution I created a custom attribute called key into which I stored the index.
newWShip.key = i;
Later when I need the index back again I can use this.key inside the JQuery .click()method:
var key = this.key;
var adt = WShipsObject.Ships[key].adt;
You could argue that in fact I could store all the data into custom attributes, but I would argue that that would be unnecessary duplication of memory.