How to reach JSON data inside parenthesis - javascript

I have a JSON response like this:
google.friendconnect.container["renderOpenSocialGadget"](
{
height: 200,
url: "http://username.github.io/",
"view-params": {"style":"light","url":"https://www.facebook.com/username","height":"258"},
"prefs": {"style":"light","url":"https://www.facebook.com/username","height":"258"}
}, skin);
I want to reach the values such as height, url, view-params but couldn't.
I tried this but it didn't worked:
console.log(google.friendconnect.container["renderOpenSocialGadget"].url);

The expression google.friendconnect.container["renderOpenSocialGadget"]( is equivalent to google.friendconnect.container.renderOpenSocialGadget(
Given that, we see that this is a method of an object, getting a JSON object and an additional parameter (skin) as parameters.
As the object is somehow "anonymous" parsed directly in to the function call, you can't access it anymore, once the function has consumed it.
Check, if google.friendconnect.container has getter methods (they usually have ...) by console.log(google.friendconnect.container).
EDIT
Just an Idea: you might catch the call and pass it over:
google.friendconnect.container["MyrenderOpenSocialGadget"] =
google.friendconnect.container["renderOpenSocialGadget"];
google.friendconnect.container["renderOpenSocialGadget"] = function(obj, skin) {
// do what you want with obj
console.log(obj.url);
//call original
google.friendconnect.container["MyrenderOpenSocialGadget"](obj, skin);
});

Related

Executing a script from jQuery GET request

I'm sending a GET request with jQuery
$.get("/index.html", /*Adding '?update' to the request*/ "update",
function (data) {/* Enter code here */}, "html");
where data is my server's response. I'm sending back a simple script like alert() so the 'data' variable equals <script> alert("Hello world!") </script>.
I need a way to automatically execute the script. I could just .append(data) to an element but I'm having multiple appends so that isn't really practical.
What is the easiest and the most practical way of executing the script?
Either .append it, like you said, or use eval(data), but then you'd have to get rid of the <script></script>. You can supply eval() a piece of Javascript code and it will execute that.
Please be aware that using eval should be avoided at all costs.
I did some crazy stuff in a case like this but you may think it is extreme. In my case I had to store some functions in localStorage and execute them by history state ( when user goes back/forth ). I have created a json object similar to
{obj:'myObject', fn: 'myfn', args: myArgs}
then stored this data base64 encoded. then when I need it back, I simply decoded content and
window.[data.fn].[data.obj].apply(null,data.args)`
did the trick without exposing too much data and not using eval. Eval comes from Evil so I would stay away. =)
UPDATE
So in my case all main core functions are json objects at window namespace similar to ( not actual content but an sample)
Member = {
initialize: function (){
//some process
},
render:function(memberId, selector){
//Some process
},
//...etc }
So when I store each item it, I used something similar to
var data = {obj: 'Member', fn: 'render', args: [1,'#member-block']}
then encoded version will be
localStorage.setItem('data', btoa(JSON.stringify(data)));
dmFyIGRhdGEgPSB7b2JqOiAnTWVtYmVyJywgZm46ICdyZW5kZXInLCBhcmdzOiB7bWVtYmVySWQ6MSwgc2VsZWN0b3I6ICcjbWVtYmVyLWJsb2NrJ319
Then when I need to call back
var data = JSON.parse(atob(localStorage.getItem('data'));
would return my original data object. Since the main functions in my case are in window namespace.
if (typeof window[data.obj]!=='undefined') { // same as window.Member
if (typeof window[data.obj][data.fn]!=='undefined' && typeof window[data.obj][data.fn]!=='function' ) { // make sure fn is defined and is a function
window[data.obj][data.fn].apply(null, data.args);
// we pass same arguments to function call with apply.
// `apply` will give us option to add arguments dynamically without knowing its size.
// it can be null any number of arguments that needed for that function.
}
}

Passing function object references as serialized json

I have written some widgets using the jquery widget factory. Normally, I pass options and callback references using the widget constructor in a JavaScript code block.
Now I want to use the widgets in auto generated html pages and pass options to them without using JavaScript blocks. I am specifying the options in embedded json which a common JavaScript code block parses and passes it on to the widget.
<div id="search_widget">
<script type="application/json">
{
"search": {
"search_string": "text to be searched",
"callback": "a function object in an outer scope"
}
}
</script>
</div>
How do I pass the function objects preserving their scope to the widgets in json format ?
The widget will then call the function specified when a condition is met.
Thanks for your help.
You can pass the function body as text, but your receiving context will have to know it's a function and "reconstitute" it with the Function constructor (or something). You can't preserve the "scope", though that doesn't really mean much in a block of JSON.
You could also pass the function name, or some identifying pattern, or anything else you like, but all on the condition that the receiving code knows how to act on that.
JSON provides no mechanism for representing a "function". The concept is completely alien to the format, and rightly so, as it's intended to be language-neutral.
edit — Note that if you encode your function by name:
<script type="application/json">
{
"search": {
"search_string": "text to be searched",
"callback": "search_callback_23"
}
}
</script>
Then the code that grabs the object and interprets the contents can always invoke the function with the outer JSON object as the context:
function handleJSON( the_JSON_from_the_example ) {
var json = JSON.parse(the_JSON_from_the_example);
if ("search" in json) {
var searchTerm = json.search.search_string;
var callback = findCallbackFunction(json.search.callback); // whatever
callback.call(json, searchTerm); // or json.search maybe?
}
}
In other words, if the code that's interpreting the JSON-encoded information knows enough to find callback function references, then it can probably figure out an appropriate object to use as this when it calls the function.

cannot access property of JSON object when dynamically built but can when statically built

I've been at this for an hour and I need help. This is kind of baffling me. Consider this explicit setup of an object in my code:
WORKING CASE:
var terms={};
terms[0]={};
terms[1]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[2]={"label":"crayon","cell_src":"images/crayon.jpg","clue_type":"audio","clue_src":"/audio/car.wav"};
terms[3]={"label":"pen","cell_src":"images/pen.jpg","clue_type":"audio","clue_src":"/audio/car.wav"};
terms[4]={"label":"pencil","cell_src":"images/pencil.jpg","clue_src":"/audio/boat.wav"};
terms[5]={"label":"pencil_case","cell_src":"images/pencil_case.jpg","clue_src":"/audio/train.wav"};
terms[6]={"label":"rubber","cell_src":"images/rubber.jpg","clue_src":"/audio/taxi.wav"};
terms[7]={"label":"ruler","cell_src":"images/ruler.jpg","clue_src":"/audio/plane.wav"};
terms[8]={"label":"sharpener","cell_src":"images/sharpener.jpg","clue_src":"/audio/taxi.wav"};
window.terms= terms;
window.terms= terms; // for using globaly
if I do a console.log(window.terms[1]); I get "bag". Thats what I want.
NOT WORKING CASE
If instead of explicitly defining the values of term{}, I read in the contents from a json file and assign them to each enumerated index like this:
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
});
if I do a console.log(window.terms[1]); I get an error "Uncaught TypeError: Cannot read property '1' of undefined" Note that I have an alternate attempt commented out where I eliminate the possibility that theres something weird going on with the values I am trying to pull in and I explicitly assign the same static value to all the indexes. That produces the same error.
Any ideas how this could be??
$.getJSON does not block when performing an AJAX call. You have to keep the callback chain a live.
I think you want to define terms as an array of objects. Currently you have it defined as an object with properties 1, 2, 3, etc. Syntax like var terms = {} means terms is an object and when you assign terms[1] = {"label": "bag"} you're saying "the property named 1 of object terms is {"label": "bag"}. Just change your terms declaration to this:
var terms = [];
Also, if you want to see the label property of one of the objects the log statement would looks like this:
console.log(terms[2].label);
The $.getJSON() function is just a shorthand for a call to $.ajax() to load a JSON file. Since the AJAX call is asynchronous, the execution of $.getJSON() completes, and any code after it is executed, before the data has been loaded and stored in your variable.
If you want to work with terms do so inside the success callback function that you're passing to $.getJSON().
If your code looks like this:
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
});
// use window.terms here
Then it won't work, because the // use window.terms here part executes before the AJAX call has finished. You'll need to move that to a separate function and call that from the success callback:
function workWithTerms() {
// use window.terms here
}
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
workWithTerms();
});

How do I relay dynamic parameters passed into a functionA() to functionB() called within functionA()

I'm trying to relay dynamic parameters from a web page into a function, which then passes them to a call inside the function. For example, take the simplified snippet below, as it is now, passing in the parameters directly is not problem. But how do I pass in a parameter which colorbox accepts without making a parameter for showColorbox() for every possible colorbox parameter?
function showColorbox(title, url, width, height, modal, params) {
$.colorbox({title:title, href:url, width:width, height:height, opacity:0.7});
}
For instance, colorbox accepts passing in an event function, such as below if I called colorbox directly:
$.colorbox({title:title, href:url, width:width, height:height, opacity:0.7,
onComplete: function() {
$.colorbox.resize();
}
});
So, without adding some code or making another parameter and parsing it out somehow inside showColorbox(), is there a way for me to pass the onComplete param/code [via showColorbox(....{onComplete:yada yada}) or something] and have them relayed to the $.colorbox() function?
UPDATE:
Ended up using the following successfully, added an extra objParams parameter to the showColorbox() function.
//m_title, m_url, m_width, m_height are from fixed parameters for showColorbox()
var objBase = {title:m_title,href:m_url,width:m_width,height:m_height} ;
var objFinal = {};
//add base parameters passed in directly, fixed params
for(var item in objBase) {
objFinal[item] = objBase[item];
}
//add the parameters from objParams passed in (variable params/values)
for(var item in objParams) {
objFinal[item] = objParams[item]
}
//call function with combined parameters in object
$.colorbox(objFinal)
None of the callers needed to be updated, but now passing in a new object using parameters which $.colorbox understands works fine! Thanks again!
It sounds like the solution you're looking for is wanting there to be a simple way to pass individual parameters of variable arguments as a named property value in an object literal. If so no there is no way to achieve this. Primarily because in this case there are no names for the arguments so there would be nothing for them to map to.
The best way to approach this problem altogether is to require an object at every stage and omit the extra parameters altogether.
function showColorbox(obj) {
...
$.colorbox(obj);
}
showColorbox({title:title, href:url, width:width, height:height, opacity:0.7});
Why not just accept one parameter which is the object you pass to colorbox?
function showColorbox(params) {
$.colorbox(params);
}
Then you can call it like this:
showColorbox({title:title, href:url, width:width, height:height, opacity:0.7});

JQuery Ajax Get Customization

Using one of the many options defined at http://api.jquery.com/jQuery.ajax/ (or anywhere else) can I map the incoming data to a specific data type rather than the default generic object that is usually returned?
My usual method is to "convert" the generated object by grabbing each property and placing it into the constructor for the new object that I really want to use. Then, I just forget about the old object. I would imagine that there is a much more efficient way to do this.
I came up with/found a few ideas such as simply adding methods to each of the returned objects. It works well, but I just have to know if there is an even more efficient method.
So you're saying that you have code like the following:
function Pirate(name, hasParrot)
{
this.name = name;
this.hasParrot = hasParrot;
}
and the server is sending this JSON data:
{
name: "Blackbeard",
hasParrot: true
}
which jQuery is converting to a plain object, right?
If that's the case, you can use a custom datatype to parse the server's data directly into a Pirate object, like so:
// First define the converter:
jQuery.ajaxSetup({
converters: {
"json pirate": function(obj) {
if(!obj.name || typeof obj.hasParrot === "undefined")
{
throw "Not a valid Pirate object!";
}
else
{
return new Pirate(obj.name, obj.hasParrot);
}
}
}
}
// Then use it!
$.ajax("http://example.com/getPirate", {
data: {id: 20},
dataType: "pirate",
success: function(pirate){
console.log(pirate instanceof Pirate); // Should be true
}
});
Edit: If you really want to skip the step of converting to JSON, you could could replace "json pirate" above with "text pirate" and write your own parser for the raw text returned by the ajax call.

Categories