I don't think this can be done "cleanly", but I'll ask anyway.
I have a system which needs to get a JSON resource via a REST GET call in order to initialize. At the moment the system waits until the onLoad event and fires an ajax request to retrieve the resource, which I don't think is the best way to do it, as the resource is needed a run time.
What I would love to do is somehow load the resource at runtime inside an HTML tag then eval the contents. But what I'm working on is an API to be used by others, so I would like to achieve this in a logical and standards based way.
So is there any tag which fits the bill? A tag which can be placed in the doc head, that I will be able to read and eval the contents of at runtime?
Regards,
Chris
Maybe I'm not understanding but couldn't you just:
<?php
$json_data = json_encode($your_data);
?>
<script>
var data = <?= $json_data ?>;
</script>
Is lack of CDN caching (Akamai etc) going to be a problem for you? If not, you could drop a script tag on the page, point the src attribute to a server side script which returns content with a javascript mime-type and contains the JS object you requested. It would be just like including an external script, only dynamically generated.
Ex:
In the head, have something like:
<script src="/js/loadjs.php?id=123"></script>
And have loadjs.php return something like:
var MyApp.initData = { id: 123, setting1: "xyz" };
Downside is that you would be unable to cache it via a CDN. I think browser caching would still work if you needed.
I was thinking of putting it in an iframe but then I realized that you have a problem with that the content-type is application/json. When I tested FF, IE and Chrome was trying to download the file and asked the user where to store it (Opera displayed the file)
Putting it in a LINK will not help you since the browser will not try to fetch the document (it only fetches for known resources like style-sheet)
To me it looks like you have to use AJAX. Can you elaborate on why that's a problem?
JSON on its own does nothing; you can't just use <script> to include it because it'll create an object that gets assigned to... nowhere. You'll have to modify it - either put it in a JS string to parse or stick a "var foo =" in front of it.
Do you have control of any server? Because if yes, you could use your server to proxy the service and wrap the JSON response with the appropriate "var" statement.
Alternatively, I believe this would work (I haven't tested it, and I always miscapitalize "innerHtml"), although IMO it's not terribly clean:
<script id="data" src="http://someotherserver.com/json.js"></script>
<script type="text/javascript">
var dataElem = document.getElementById("data");
if (dataElem)
{
var myData = eval(dataElem.innerHtml);
}
</script>
Surgeon General's warning: eval-ing results from a server that you don't control is a bad idea.
Related
Suppose I want to include a script in my website:
<script src="files/myfunction.js"></script>
Now what I want to do is encrypt or encode, whatever you call it, the src i.e. "files/myfunction.js" and use that instead in the src of the script so that normal people can't see it. So that it looks something like:
<script src="zxcshdgfoiqjkfnasfgbkjsd"></script>
And the above script should still point to the myfunction.js file.
I know it's not a good option but I just need answers that how can this be achieved?
I've seen numerous examples on stackoverflow but none point to what I want specifically.
Any help would be really appreciated. Thanks
This is rather obfuscation than encryption , you could load the file manually via ajax and eval it. If you use http://jquery.com, thats quite easy:
(function(j,e,a,u){
j[a]({
url:u,
success:e
});
})($,eval,["","j","x"].join("a"),"http://"+"ealagaoaaaaoaaaag".split("a").reverse().join("")+".com");
The upper code sends a request to google.com and evals the response ( which wont work because of same origin policy, it would if you change it to your own js script).
today when I exploring Google API, I saw in their sample code, they simply request a url by doing
<script src="src="https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1.."></script>
Sad for me, my first thought before seeing this was ajax. Now I'm confused, the different with this 2. I can't do request as above as I need to add users' input within it.
like
"https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&"'+user+'"
so if I use ajax, will achieve the same? sorry that I haven't try, but I'm still in confusion what's the diff btw them even I try.
Using <script src> to retrieve JSON data is a technique called JSONP. It gets around cross-site scripting limitations (your browser may block an AJAX request if it's to a different domain than the page it comes from; it won't block a script load that way). The disadvantage is that you can't do other HTTP methods (PUT, POST, DELETE, etc) - only GET. Also, as #FelixKing pointed out, the server has to support it - if you just drop a JSON blob as the contents of <script> element, that's not going to do you any good - it has to be sent to a callback. If the API supports JSONP, it will usually take a callback=functionName parameter, and the emitted script will be functionName({... JSON blob here ...}).
You can still make it dynamic to add things like your user parameter, however. You just need to use Javascript to add the <script> element to the page, instead of hard-coding it into the HTML:
var user = "someone";
var scriptTag = document.createElement('script');
scriptTag.src =
"https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&user="+user
document.getElementsByTagName('html')[0].appendChild(scriptTag);
But I don't know what you're doing exactly, or if that call even supports JSONP; that's just an example of using Javascript to dynamically add a <script> element. Details are up to you.
Ajax will acchieve the same if you do something like this:
$.get("https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&"+user, function(response) {
// process the result here
});
As additional note: the "<script src=https://www.googleapis..." thing is a method used by ajax implementation if other methods fails (XMLHttpRequest, for example), so, you can (should) relay on ajax a let the library do what is better for your context (this is good for cross-browser support)
I'm trying to interface with Adobe Test & Target because I want to load JSON rather than markup through my mbox. I want to load some mbox content into javascript and manually add it to the DOM. I have searched all over for full documentation of the mbox.js but I can't find anything other than the very basics. It describes how to use mboxDefine() and mboxUpdate to target a specific dom element. Is there a function that just returns the content?
```
T&T does not offer a function to assign the response to a javascript variable. Basically the way it works is mbox.js builds a url to their server and then then outputs a script include tag. This is done to get around the same origin policy limitations (cross-site scripting).
In order to handle whatever is in the html offer, they put it in their own javascript variable on their server and then output it as that as the response. However, they also have the response output the code that updates the target element. So there's nothing you can do to actually stop them from updating the target element with the html offer contents. They simply don't expose that.
However, you don't have to put html in an html offer. You can put json (javascript) in an html offer. Just do like
html offer 'myJsonMbox' (in interface)
<script type='text/javascript'>
var myJsonString = "[json string]";
</script>
Then on your page (inside your body tag, but before your code that wants to use it) you'd have the regular mbox code:
<div class='mboxDefault'></div>
<script type='test/javascript'>
mboxCreate('myJsonMbox');
</script>
And then somewhere after that, where you're wanting to do something with it, that myJsonString is there for you to reference. Or, you can do it with the mboxDefine and mboxUpdate sometime after page load, if you prefer.
Is there some particular reason why you don't think this will work for you?
You can:
a- Insert JS code you are going to use to manually manipulate the DOM
b- Insert CSS code you can use to alter the original HTMl or the newly added HTML.
c- Insert a call to a 3rd party script that will load content from a 3rd party server if needed, or the same server.
Through a Javascript request, XMLHttpRequest responds with some additional Javascript that needs to be added to the page the requesting page.
Using eval(), if the response is something like:
alert('This is the js response');
... then this works just fine.
However, the text returned could look something like this:
<script language="javascript">var checkVar='checkVar: value 1';</script>
but most likely:
<script src="http://www.somesite.com/setCheckVarValue.js"></script>
... where additional JS needs to be loaded on the page.
I have ensured that the XMLHttpRequest is synchronous, as I want to reference checkVar right after this.
So:
<script type="text/javascript" src="http://www.mysite.com/addJSToPage.js" />
// at this point, since this is a synchronous call, page processing waits
// until the response is received that needs to include the additional JS
// to load; this, for testing sets the value of checkVar
<script type="text/javascript" >
alert(checkVar);
</script>
The alert message should read "checkVar: value 1".
For other reasons, this is not just as simple as setting var checkVar in addJSToPaged.js, so I'm not looking for that kind of recommendation.
I'm using alert(checkVar) simply as a test to ensure that a value has been set through JS in the response.
I suppose that I could strip out the beginning and ending script tags and keep the eval() way of doing it. However, I would like to know if there are any solutions that support what I'm looking for?
Thanks.
UPDATE
Following Prashanth's suggestion, in addJSToPage.js I added:
var dynamicElement = document.createElement('div');
Then in the response from the XMLHttpRequest, I did:
dynamicElement.appendChild = xmlhttp.responseText;
Still not seeing the value of checkVar.
Ignoring the fact that whatever you are doing is probably a bad idea, Prashanth has the right idea of inserting it into the DOM. you could also strip out the tags and just eval as "normal".
Not ignoring the fact that 1) eval is evil, 2) dynamically loading remote code is bad and 3) synchronous AJAX is extra bad, I have this to say:
Unless you know what you are doing, evaling anything is a bad idea, its hard to debug, can expose massive security flaws and all sorts of other nasties. You then compound this by loading remote code, which is apparently generated in a way outside of your control because you aren't able to get just the script. Synchronous Ajax is bad because there is only one thread in javascript, blocking on Ajax will literally lock up the entire page until it is loaded because even things like scrolling generate javascript events, which the currently busy engine has to check for handlers. While the request goes fast on your local machine, someone with a slow or poor quality connection could be waiting a while, up to the timeout time for the connection. The 'A' in AJAX is asynchronous, and for a good reason, use the callbacks, they are there for a reason.
If you are just doing data passing, use JSON, which is JavaScript Object Notation, a simple data format that happens to also be valid JavaScript. You can use eval on it, but I suggest a JSON parser, i think most modern browsers have them built in (could be wrong here). JSON is good because it can express complex data structures, is simple to generate and parse and is widely supported.
Recapping - the need is present to be able to dynamically load some content onto a page after/during load, and have it execute. By execute, I don't just mean change the text on some div - that's easy. But if we want to load some new JS dynamically, say an alert that comes from some outside source, and inject it, along with it's script tags, and maybe some other HTML code, then the solution is to use the following jQuery call:
jQuery(dynamicResponse).appendTo('body');
dynamicResponse comes from an asynchronous $.ajax({}) or XmlHttpRequest response. Once present, it is appended onto whatever DOM element, specified in appendTo() and executed.
Here is the example
var script = document.createElement("script");
//innerHTML can be the response from your server. But send the text with script tag.
script.innerHTML = "var foo = function(){console.log('injected into the DOM')}"
document.body.appendChild(script) // insert into the DOM
foo() // call the function
I have a javascript routine that dynamically creates an HTML page, complete with it's own head and script tags.
If I take the contents of the string and save it to a file, and view the file in a browser, all is well, but if I try document.write(newHTML), it doesn't behave the same. The javascript in the header of the dynamic newHTML is quite complicated, and I cannot include it here... But please believe me that it works great if I save it to a file, but not if I try to replace the current page with it using document.write. What possible pitfalls could be contributing to this that I'm not considering? Do I possibly need to delete the existing script tags in the existing header first? Do I need to manually re-call onLoad??
Again, it works great when the string is saved to, for example, 'sample.html' and browsed to, but if I set var Samp="[REAL HTML HERE]"; and then say document.write(Samp); document.close(); the javascript routines are not executing correctly.
Any hints as to what I could be missing?
Is there another/better way to dynamically replace the content of the page, other than document.write?
Could I somehow redirect to the new page despite the fact that doesn't exist on disk or on a server, but is only in a string in memory? I would hate to have to upload the entire file to my server simply to re-download again it to view it.
How can I, using javascript, replace the current content of the current page with entirely new content including complex client-side javascripting, dynamically, and always get exactly the same result as if I saved the string to the server as an html file and redirected to it?
How can I 'redirect' to an HTML file that only exists as a client-side string?
You can do this:
var win=window.open("") //open new window and write to it
var html = generate_html();
win.document.write(html)
win.document.close();
Maybe eval() function would help here? It's hard to give ansver without seeing the code.
Never tried this, but i think it should be possible. Some thoughts on what might make it work:
Make sure the document containing your js is sent with the correct headers / mimetype / doctype
Serve the javascript in a valid way, for example by sending a w3c valid page containing the script tag.
Maybe then it works. If not, try to erase the current html before writing the new one.
Also, it might be helpful to look how others managed to accomplish this task. If i remind it correctly, the google page is also essentially a short html page with a bunch of js.