I want to cast a string to an existing object.
Background: I am using only JS, no libraries and no server side code. I have existing objects with elements I wish to display. I pass the name of the object using a query string so it arrives as a string. Example ?Room=Cube and what I wind up with is
nextRoom = getQueryString(); // which returns a string
and I want to display the Cube object. However nextRoom contains "Cube" and JS is not helpful, if I call a display function:
display(nextRoom)
Javascript treats it as a string and fails. Currently I fake it out with the object:
castToObj{"Cube":Cube, "Other":Other, "Etc":Etc, ........}
.....
room = castToObj[nextRoom]; // accessing the object returns the room Object
then I can display the room by calling:
display(room); // now JS treats the parameter as an object
But this requires me to rewrite code to modify the castToObj{} contents every time I add a room. I would like a way to turn "Cube" into Cube, in other words turn a string into an object. I have tried many variations but have been unsuccessful. I could list ways I have tried but that seems senseless because they were all failures.
HELP! PLEASE!
P.S I retired about twenty years ago before learning C++, OOP, etcetera so my javascript skills are just my "C" programming experience expanded.
First create an empty container object:
myElements = {};
Then change your code wherever you define an element, from
Cube = ... whatever ...
to
myElements.Cube = ... whatever ....
for all of your elements (Other, Etc ...).
After this, you simply use
nextRoom = getQueryString();
display(myElements[nextRoom]);
You can use java script eval function but depending on the situation it might open your program to XSS attack. You should use it carefully.
Related
I'm very new to rails, so please bear with me. I haven't quite grasped all the "magic" just yet.
Basically I need to access Location objects in Javascript, which all contain 0-N Coordinates. I'm pretty sure the model is set up right, with each Coordinate having a location_id.
I managed to get a parsed JSON of Location objects using the following method: I put
def index
#locations = Location.all.to_json
end
in the controller, and accessed this in the view with
var theLocations = <%= #locations.html_safe %>;
when I show this variable in the log, however, it doesn't show the Coordinates, which kind of makes sense. Thing is, I was planning to iterate over all the Locations and for each one create a javascript var with the relevant coordinates. These vars would then be passed to Google maps as objects.
Basically I was planning on doing something like (pseudocode):
for(Location l in Locations){
get all Coordinate objects within Location
for(Coordinate c: Coordinates);
var myObject = new google.maps.LatLng(c.X, c.Y),
add myObject to list for this location.
}
}
I'm just not sure how to approach this. How can I get a reference to the Coordinates within the Locations?
The quick and dirty answer is to pass a parameter in your to_json call:
#locations = Location.all.to_json(:include => :coordinate)
You may also want to consider creating a custom JSON structure by overriding as_json and rendering the objects as JSON after that.
I have a dynamically created list, but each element is a pretty big HTML chunk that has a common structure and a few variables.
What would be the best way to do it with jQuery?
One way to handle large amounts of HTML in the client is to use atemplate system. If you want to keep it jQuery centric then jQuery templates are one option but I believe it has been dis-continued.
I've had a lot of success with Underscore templates, which are fast and easy to use.
Not sure if this is overkill for you, but maybe check out a templating library.
https://github.com/janl/mustache.js is really good I've heard (personally haven't used it).
I've used the one from Underscore.js
The latter would look something like this..
var myTemplate = _.template("<div>This is my reusable block with {{ count }} variables");
$.each([1,2,3,4], function(elm, i){
$('body').append(myTemplate ({count: elm}));
})
Here's a jsfiddle example http://jsfiddle.net/K8VHb/
I'll echo what CambridgeMike and Simon Smith said, "Use a template library," except that I'll plug a different and I think better one. Use Handlebars.js. It's the same one Ember.js picked, it's great standalone and it pairs well with Backbone.js as well.
It's something you can use for a long time.
Taking advantage of the join method of arrays (concatenates elements into strings) is my favorite approach. Using this along with JQ, I've never really understood the appeal of JS templating libraries. It's also convenient for formatting HTML in an easy-to-read style without sweating line-breaks in JavaScript. I didn't test this so there may be syntax goofs.
var standardList = [
'<li>Always here</li><!--could add a bunch more non-variable LIs here-->',
'<li>',
, //this is key #2 - one comma per line at the end makes counting easy
'</li>',
'<li>More non-variable LIs</li><!--possibly more non-variable LIs here-->',
'<li>',
, //this is key #6
'</li>'
];
//you could have lots of these or an array of them dropped in from a server
var variableListItems = {
key_2:'first Var list value',
key_6:'second variable list value'
};
function buildFromListTemplate(valuesObj,listTemplate){
for(var x in valuesObj){
listTemplate[x.split('_')[1]] = valuesObj[x];
//x.split('_') returns array ['key',<number>] for each key in object
//so [1] gives array key
}
return listArray.join(''); //smooshes array into one big string
}
$('#someExistingUL').html(
buildFromListTemplate(variableListItems, standardList)
);
Note: A powerful but easy upgrade would be to handle the LI-wrapping of values inside the buildFromListTemplate function. That way, the keys you put inside your values object would all be optional and wouldn't leave a blank LI when not provided.
When it comes to formatting big hunks of HTML, split/join are your friend and have powerful utility in general. Another handy use is to build a list or table row from an existing set of values:
var ulHtmlString = [
'<ul><li>',
arrayOfValues.join('</li><li>'),
'</li></ul>'
].join('')
You can build on this to auto-convert 2D arrays into tables as well. Learn some regEx (which can be used in place of strings in the split method) and you can easily convert back from HTML to data-only arrays and objects in cases where the HTML isn't uniform.
i would use jQuery templates.
using jquery templates consists of two pieces:
your template (usually HTML):
<script id="myTemplate" type="text/x-jquery-tmpl">
<div>${text} ${otherStuff}</div>
</script>
and your data (usually JSON or a javascript object):
var data = { text: 'hello world!', otherStuff: 'foobar' };
Then you just bind the data to the template
var resultingHTML = $('#myTemplate').tmpl(data);
then append the resulting HTML to your DOM:
$('#someContainer').append(resultingHTML);
jQuery templates offer a lot of flexibility with conditionals/loops in your templates such as {{if}} and {{each}}, and JSON is a very easy data transfer language to work with.
I have an application that lets users build things in JS. I want the user to be able to save the current state of his work to reuse it or share it, but what he has is a collection of JS objects stored in a JS array, with very different properties (color, label, x/y position, size, etc.).
SQL seems terrible for that particular task, forcing me to maintain tables for every different object, and alas I know very little about NoSQL database. What tools would you use to perform this ? MongoDB sounds promising but before I learn a whole new DB paradigm I want to be sure that I am heading in the right direction.
Object to string:
You can store your objects in the DB as a JSON string. Here's a simple example:
var foo = new Object();
foo.Name = "James";
foo.Gender = "Male";
//Result: {"Name":"James","Gender":"Male"}
var stringRepresentation = window.JSON.stringify(foo);
Here's a working fiddle.
String to object:
To convert your string back to an object, simply call window.JSON.parse():
var myObject = window.JSON.parse(stringRepresentation);
Here's a working fiddle.
If you have no interest in quering the objects for their various properties but only persist them to save state, you can serialize the entire array to JSON and store it in any db you like as one string.
What's on the server?
Most languages have mature JSON implementations that convert JavaScript objects to native types, which you can then easily store in a SQL database.
Basically, I'm working on a page that includes four different JSON "thingies" (objetcs,arrays). Forgive my lack of proper terminology.
When I get the JSON, it comes in as an object with a bunch of sub-objects, and each "sub-object" looks like this:
"token":"government",
"title":"Government",
"isSelected":false,
"type":"CATEGORY",
"subtype":"INDUSTRY",
"count":12
So the first task is to loop through each JSON and populate a box full of checkboxes, using the title as the label and the isSelected to indicate the checked status. So far, so good.
BTW, somewhere aslong the way, I picked up a JS script that checks whether an object is JSON or an array, and according to that "quick & dirty" test, my object is an array. Or an array object (you know, the one is created with [ ] and the other with { })?
Anyway, when the end user checks and un-checks checkboxes, I need to keep track of it all and immediately send back changes to the server (when the user clicks a DONE button). The crazy thing is that by looping through the objects, I was able to change the isSelected value to true . . . just not back to false.
for(var i = 0; i < $array.length; i++){
$array[z].isSelected = true;
}
Perhaps I was up too late when I worked on all of this, but using the same approach, I could not change $array[z].isSelected to false when the checkbox got de-selected.
In the end, I converted the JSON "thingy" to a string, search and replaced the corresponding values, and then converted the string back into an object. This is all working now, but I feel as though I've just used up a roll of duct tape on something that could have been put together by snapping the pieces together nicely.
Question: Did I miss the boat totally and is there a simple way to change values of JSON objects?
If so, could you point me in the right direction?
That JSON thingy is just a string representation of a javascript object.
One way of creating an object is
var myObject = {
"myName": "AName",
"myType": "AType"
};
This object can be referenced as myObject, with the properties myObject.myName and myObject.myType containing values AName and AType.
You should be able to just reference the object by name as objName.token objName.title etc.
If you have trouble try parsing the json with javascript then reference the result as above. This should make it easier for you to access, manipulate or delete data in the objects properties as well.
The nesting of these as below can be referenced as myObject.moreProperties.prop1 etc
var myObject = {
"myName": "AName",
"myType": "AType",
"moreProperties": {
"prop1": "vaue1",
"prop2": "vaue2",
}
};
I need to implement a simple way to handle localization about weekdays' names, and I came up with the following structure:
var weekdaysLegend=new Array(
{'it-it':'Lunedì', 'en-us':'Monday'},
{'it-it':'Martedì', 'en-us':'Tuesday'},
{'it-it':'Mercoledì', 'en-us':'Wednesday'},
{'it-it':'Giovedì', 'en-us':'Thursday'},
{'it-it':'Venerdì', 'en-us':'Friday'},
{'it-it':'Sabato', 'en-us':'Saturday'},
{'it-it':'Domenica', 'en-us':'Sunday'}
);
I know I could implement something like an associative array (given the fact that I know that javascript does not provide associative arrays but objects with similar structure), but i need to iterate through the array using numeric indexes instead of labels.
So, I would like to handle this in a for cycle with particular values (like j-1 or indexes like that).
Is my structure correct? Provided a variable "lang" as one of the value between "it-it" or "en-us", I tried to print weekdaysLegend[j-1][lang] (or weekdaysLegend[j-1].lang, I think I tried everything!) but the results is [object Object]. Obviously I'm missing something..
Any idea?
The structure looks fine. You should be able to access values by:
weekdaysLegend[0]["en-us"]; // returns Monday
Of course this will also work for values in variables such as:
weekdaysLegend[i][lang];
for (var i = 0; i < weekdaysLegend.length; i++) {
alert(weekdaysLegend[i]["en-us"]);
}
This will alert the days of the week.
Sounds like you're doing everything correctly and the structure works for me as well.
Just a small note (I see the answer is already marked) as I am currently designing on a large application where I want to put locals into a javascript array.
Assumption: 1000 words x4 languages generates 'xx-xx' + the word itself...
Thats 1000 rows pr. language + the same 7 chars used for language alone = wasted bandwitdh...
the client/browser will have to PARSE THEM ALL before it can do any lookup in the arrays at all.
here is my approach:
Why not generate the javascript for one language at a time, if the user selects another language, just respond(send) the right javascript to the browser to include?
Either store a separate javascript with large array for each language OR use the language as parametre to the server-side script aka:
If the language file changes a lot or you need to minimize it per user/module, then its quite archivable with this approach as you can just add an extra parametre for "which part/module" to generate or a timestamp so the cache of the javascript file will work until changes occures.
if the dynamic approach is too performance heavy for the webserver, then publish/generate the files everytime there is a change/added a new locale - all you'll need is the "language linker" check in the top of the page, to check which language file to server the browser.
Conclusion
This approach will remove the overhead of a LOT of repeating "language" ID's if the locales list grows large.
You have to access an index from the array, and then a value by specifying a key from the object.
This works just fine for me: http://jsfiddle.net/98Sda/.
var day = 2;
var lang = 'en-us';
var weekdaysLegend = [
{'it-it':'Lunedì', 'en-us':'Monday'},
{'it-it':'Martedì', 'en-us':'Tuesday'},
{'it-it':'Mercoledì', 'en-us':'Wednesday'},
{'it-it':'Giovedì', 'en-us':'Thursday'},
{'it-it':'Venerdì', 'en-us':'Friday'},
{'it-it':'Sabato', 'en-us':'Saturday'},
{'it-it':'Domenica', 'en-us':'Sunday'}
];
alert(weekdaysLegend[day][lang]);