i have an object that stores a table for converting a json response in a user readeable text. The thing is, the same text applies for multiple json conditions.
I want to know if there's a way to set the same value for 2 different Id's in a object.
Like, instead of:
var msg = {
"error_code1": "user_msg",
"error_code2": "user_msg",
}
Something like this
var msg = {
"error_code1" && "error_code2": "user_msg",
}
Is it possible?
First approach is using "getter" functions to reference the initial object:
var errorBindings = {
'errorCode101': 'Unauthorized request',
get 'errorCode102'() { return this.errorCode101; },
get 'errorCode103'() { return this.errorCode101; },
'errorCode104': 'All fields are required',
get 'errorCode105'() { return this.errorCode104; },
};
console.log(errorBindings.errorCode103); // "Unauthorized request"
Second approach is using an anonymous function with referencing properties from which we should borrow the needed value:
var messages = function(o) {
o.errorCode101 = 'Authorization error!';
o.errorCode102 = o.errorCode101;
o.errorCode103 = o.errorCode101;
o.errorCode104 = 'All fields are required';
return o;
}({});
console.log(messages.errorCode101); // "Authorization error!"
console.log(messages.errorCode103); // "Authorization error!"
What about:
var msg = {};
msg['a'] = msg['b'] = 'value';
But for such simple cases I prefer to repeat myself instead of doing premature optimizations.
Unfortunately in JSON all keys must be strings so what you are attempting will not work.
As a work around I can suggest storing a reference to the value of the user_msg and assigning it to each error code key.
For example:
var storedMessage = "user_msg";
var msg = {
"error_code1": storedMessage,
"error_code2": storedMessage
}
Let me know if you have any questions.
What am I doing wrong, and how can one pass variables to a different function within the same wrapping variable/function.
Example:
function customFunctionWrap(){
this.myVar1 = 0;
this.getCurrentPosition = function(){
if (navigation.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){});
}
},
this.doSomething = function(){ // Works
//Do something, return
this.callWithParams(); //Works
},
//If I remove passing in 'value1',calling it elsewhere works
this.doSomethingWithParams = function(value1){
//Use value1
//Return
},
this.callWithParams = function(){
var value1 = 'xyz'; //Is a variable that changes based on some DOM element values and is a dynamic DOM element
this.doSomethingWithParams(value1); //THROWS TYPEDEF ERROR: this.doSomethingWithParams is not a function
this.getCurrentPosition();
}
};
var local = new customFunctionWrap();
local.doSomething(); //WORKS
I know there is another way to do it and then directly use customFunctionWrap.callWithParams(), but am trying to understand why the former approach is erroring out.
var customFunctionWrap = {
myVar1 : 0,
callWithParams : function(){
}
}
What JS sees:
var customFunctionWrap = (some function)()
returned function is fired, because the last (), so it has to yield/return something, otherwise, like in your code it is "returning" undefined.
So your given code does not work.
The very first fix is to delete last 2 characters from
var customFunctionWrap = (some function)()
to make it return constructor.
In the following code, it should store 26 different variables under the object GameThumbs for each of the 26 objects in r.Showcase
However, all that is stored is Object {26: "http://t3.rbxcdn.com/1e2476473494bfb202592501a5f86655"}
I don't see anything wrong with my code, please help me fix it. Thank you (sorry if I am not describing the problem well enough; my English is not very well)
function info(id) {
var User = {};
var GameIds = {};
var GameNames = {};
var GameThumbs = {};
$("html").html("");
$.get('http://api.roblox.com/Users/'+id, function(r) {
User['Username'] = r.Username;
}).done(function() {
$.get('http://www.roblox.com/Contests/Handlers/Showcases.ashx?userId='+id, function(r) {
for (var x in r.Showcase) {
GameIds[x] = r.Showcase[x]['ID'];
GameNames[x] = r.Showcase[x]['Name'];
var link = 'http://www.roblox.com/item-thumbnails?params=%5B%7BassetId:'+GameIds[x]+'%7D%5D';
$.get(link, function(d) {
GameThumbs[x] = d[0]['thumbnailUrl'];
});
}
}).done(function() {
console.log(User, GameIds, GameNames, GameThumbs);
});
});
}
Requested sample JSON (of link)
[{"id":45778683,"name":"Temple of the Ninja Masters!","url":"/Temple-of-the-Ninja-Masters-place?id=45778683","thumbnailFinal":true,"thumbnailUrl":"http://t0.rbxcdn.com/6eb2d1f05d120757ae1e72d8e28c918e","bcOverlayUrl":null,"limitedOverlayUrl":null,"deadlineOverlayUrl":null,"limitedAltText":null,"newOverlayUrl":null,"imageSize":"large","saleOverlayUrl":null,"iosOverlayUrl":null,"transparentBackground":false}]
of /Contets/Handlers/Showcases.ashx...
{"Error" :"", "Count" :"43", "UserIsAtMaxShowcases":"false", "Showcase" : [{"ID":164081122,"Name":"For ShrekIetsky"}, {"ID":163393918,"Name":"N7"}, {"ID":162493258,"Name":"Hackathon 2014"}, {"ID":158445333,"Name":"bests kings"}, {"ID":157560077,"Name":"Don't be an idiot."}, {"ID":157183481,"Name":"Lots of Thumbnails"}, {"ID":156339175,"Name":"Watch out!"}, {"ID":155669451,"Name":"YES I AM BIASED"}, {"ID":155669434,"Name":"Place_4"}, {"ID":155669424,"Name":"Place_3"}, {"ID":155669403,"Name":"Place_2"}, {"ID":155669381,"Name":"Place_1"}, {"ID":153242188,"Name":"earth2noah"}, {"ID":152827982,"Name":"Buying Egg Merch?"}, {"ID":152563337,"Name":"Inside Mallowpuff's head"}, {"ID":151207481,"Name":"nothin to see here"}, {"ID":151117405,"Name":"Acronym test"}, {"ID":149734880,"Name":"TESTING"}, {"ID":146087560,"Name":"FPS maps"}, {"ID":144140735,"Name":"Old Memories"}, {"ID":144035150,"Name":"Quitting"}, {"ID":142668569,"Name":"Challange Projecto"}, {"ID":140204830,"Name":"Element Obby! [Beta]"}, {"ID":140201014,"Name":"NEVERMIND KIDS C:"}, {"ID":138010986,"Name":"Passage of the Mind"}, {"ID":138006022,"Name":"I see you"}, {"ID":135852345,"Name":"Trade Information!"}, {"ID":135303493,"Name":"Future project"}, {"ID":129885802,"Name":"ololwoaplsiaeo"}, {"ID":129768085,"Name":"SiIencedSong's Place Number: 16"}, {"ID":127537299,"Name":"olopio"}, {"ID":120338485,"Name":"LmaD building!"}, {"ID":120338432,"Name":"Maze Daze [INACTIVE]"}, {"ID":120338402,"Name":"Volcano Survival maps"}, {"ID":120338370,"Name":"[[OpenSource]]"}, {"ID":120338338,"Name":"Yes"}, {"ID":120338296,"Name":"No"}, {"ID":120338264,"Name":"hackathon0n stuff"}, {"ID":118933268,"Name":"-"}, {"ID":118932768,"Name":"Testing"}, {"ID":118573473,"Name":"ROBLOX fame HQ."}, {"ID":118324272,"Name":"Simple spawnroom"}, {"ID":117834273,"Name":"Lightningsurvivor's fort."}] }
It's the same old problem with asynchronous code.
When you iterate with for...in, x changes. When the callback function of $.get is called for the first time, for has completed its iterations and x now yields the last value of the iterations, which is presumably 26.
You have two solutions for this:
make the $.get call synchronous (bad, never do this);
create a closure for the iteration.
Using jQuery, for example:
$.each(r.Showcase, function(x) {
...
$.get(link, function(d) {
GameThumbs[x] = d[0]['thumbnailUrl'];
});
});
instead of for (var x in r.Showcase). This way, x is a local variable inside the callback function of $.each, and its value will be the same when returning from $.get.
I get undefined whenever I get the value of a property of an object.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report.id, // i get undefined
reportPath: report.path // i get undefined
};
...
}
services.js
angular.module('project.services').factory('services', function(){
var reports = [
{
....
},
{
....
}
];
function getReportInfo(id){
var report = reports.filter(function(element){
return element.id === id;
});
};
return{
getReportInfo: getReportInfo
};
}
Whenever I put breakpoint on my var report = services.getReportInfo(id) it could contains the correct values for each property of the my report object. However, when I get the report.id or report.path, I get undefined value.
--Edited--
Oh, I know now where I got wrong.
The getReportInfo function returns an array and I'm accessing the properties without telling from what index should it get the values for the said properties.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report[0].id,
reportPath: report[0].path
};
...
}
I placed static index 0, since I know that the array will always have a length of 1.
You are not returning anything from the .factory method and the getReportInfo is also not returning anything. For what you are trying to do, try to use .service method:
angular.module('project.services').service('services', function(){
var reports = [
{
....
},
{
....
}
];
this.getReportInfo = function (id){
var report = reports.filter(function(element){
return element.id === id;
});
return report;
}
}
Here is a good explanation on how to use .factory and .service:
Confused about Service vs Factory
Two immediate issues with the code I can see:
1) Your factory function needs to return a value or constructor function. Right now your code is not initializing the factory to any value.
2) Your getReportInfo function also doesn't return a value, yet you are assigning the function result to a variable.
Read more here: http://docs.angularjs.org/guide/dev_guide.services.creating_services
I'm tring to get some json to contain a function so that the option in the plugin gets the returned value of the function that was in the json string.
The set up is as such:
default.txt
[
{
"element":"a[href$='.jpg']",
"options":{
"label":"test"
}
},{
"element":"a#hover",
"options":{
"label":(function(ele){ return 'test'; })()
}
}
]
and the plug-in is
(function($) {
function defined(obj){return typeof(obj)!=='undefined';}
function evaluate(ele, obj) {
if(typeof obj === 'function') {
//alert('is function');
obj = obj(ele);
}else{
try{
//alert('thinking it may be a function still');
obj = eval("("+obj+"("+ele+"));");
//obj = (obj)(ele);
}catch(err){
//Handle errors here
//alert('not function');
}
}
return obj;
}
function debug(message) {
console.debug(message);
}
$.set = function(options){
var settings = $.extend({}, {}, options);
if(defined(settings.actions)){
$.each(settings.actions, function(index, value) {
$(value.element).do_action(defined(value.options)?value.options:null);
});
}
}
$.fn.do_action = function(options) {
// Add event handler to all matching elements
return this.each(function() {
var ele = $(this);
var settings = $.extend({}, $.fn.do_action.defaults, options);
var label= evaluate(ele, settings.label);
var message = "label:'" + label + "'";
debug('Tracking ' + action + ' ' + message);
});
};
$.fn.do_action.defaults = {
label : function(ele) { return ele.attr('href'); }
};
}(jQuery));
and the control is
$.getJSON('default.txt' , function(data){
$.set({
actions:data // this si where we pull in the options
});
});
I seems to work if I put in an alert inside the anonymous function, so from
"label":(function(ele){ return 'test'; })()
to
"label":(function(ele){ alert('test') })()
but after that I can't seem to get it to print right in the console as I only get the message
Tracking label:'(function(ele){ return 'test'; })
[EDIT]
Please stop saying that "you should not put code in json". If you work for Google and are their top level programmers getting paid the big super bucks then I'll listen to the why's, but I'm sorry if it's good for them, it'll work for me. Don't know what else to say, I already understand the point of why you should avoid it which I aim to do as well. There are times when you just can't and why i supect Google does the same.
Your label member is not a function; it's a value returned by a function. The final () at the end means "execute this function immediate whenever the value of label is requested and provide its return value as the value of label".
That said, if you must include functions in your JSON object (and from what you've said, you do) your best bet is to stringify-and-eval your functions. You should also be able to use raw functions in your JSON, like {foo : (function(){ ... }) }, though I've personally had a tricky time getting this right (but that's just me -- if you can get it right, go for it).
(As an aside, it's not possible to stringify functions from existing objects, but if you're getting your functions as text from user/programmer input, that's not an issue.)