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)
Related
I am using Slick JS to create a slider, adding slides to it using AJAX and the slickAdd method as follows:
$.getJSON(url, function(r) {
$.each(r, function(i, article) {
var html = 'HTML string created with data and ' + article.variables + ' from JSON';
$('.element').slick('slickAdd', html);
}
}
This AJAX works and the slides are successfully added to the slider after the browser has all the XHR data.
The fact that it's a Slick JS slider is simply context; I believe the question is more generic than that.
Main Question: Can I force the each loop to output the 'html' while the XHR data is still being loaded by AJAX, thus giving the user the experience of a more performant site as slides are added to the DOM as quickly as possible? If yes, how?
While the funciton is looping through the 'each', I can see discrete XHR data for each item returned, and I ideally wanted to start adding to the DOM (with a delay) before all the iterations are complete.
The site is primarily PHP, so if there isn't really a "clean" way to handle this in JS / jQuery on the front-end, I can do something server side with PHP ob_flush, but just wanted to beg some JS masters (opinionated) suggestions/criticisms first.
I don't necessarilly need a full code example, just a high-level explanation - I am just a bit noob with JS.
Many thanks ;P
TL:DR; Not with a single request.
If you were to use the underlying XMLHttpRequest object to perform the AJAX request you would be able to get updates as the data is coming back from the server and potentially perform updates while the data is being loaded.
However, the obvious problem with doing this, is that the JSON won't be valid until it has been completely loaded. Although you could parse it manually, it's unlikely to be worth the effort to do so.
The only work-around to do what you want would be to send separate requests for each block of data and process them separately.
I have an ajax script which references something in the same domain. I want to pass some HTML and then javascript associated with it. I figured that since it is not X-domain, It might let me do that. My goal is that I am taking a webservice and then returning a string which will be put into a div... when the javascript is inserted it would be fired, which allows a bunch of good stuff to happen.
I was wondering if there is anything special i need to do to pass javascript from the server across this request. My current AJAX request seems to sanitize and remove the scripts. THoughts? How would i go about this?
If you want script to be included in the AJAX response and executed by the browser, you will first need to do something similar to the article posted as a potential duplicate, excepting that you have HTML to be injected as well. Proceed injecting it as normal, but after you set the content, try something such as:
$(responseText).find("script").each(function(index, element){
var script = $(element).text();
eval(script);
}
Untested
However, I would try to find a way to avoid doing the above. JQuery provides ways to handle classes of elements added dynamically to the DOM. See: http://api.jquery.com/on/
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 was wondering if someone could explain the difference between using Javascript's eval(), and another approach, like using JQuery to create script tags and then appending that element to the page:
eval(somecode);
vs.
$("<script type='text/javascript'>"+somecode+"</script>").appendTo("head");
Not sure if this is relevant, but here's the context: I'm working with a version of the Drupal Popups module whose basic purpose is to easily turn regular links into popups by AJAX'ing an entire page request and appending it to the page in a modal window. This frequently includes external CSS and Javascript files. In an effort to improve the performance of all this AJAX loading I switched over to use AJAX queueing, and I changed an eval() of external scripts into the alternative listed about. However, that caused sporadic Javscript bugs on various other pages.
Well one (as far as differences go) is eval will return the result of an expression.
var result = eval('3+4'); // result = 7
As long as your javascript string is in the structure of a script block, i would suggest injecting it within a script tag/
Adding script tags will load the scripts synchronously, whereas loading when you eval text via XHR, that was loaded asynchronously. Because of the async, the scripts were probably loaded out of order.
Note there are a billion if-but-then cases to this, but I'm guessing this is the case based on your scenario.
Now, you could load the XHR synchronously, but then things will drastically slow down. Browsers can load six (ish) scripts at once but execute them in order. The XHR will load one at a time.
I strongly suggest using JSON-P.
Add a callback function name on the outgoing AJAX request by creating a script node on the fly (with src=[url]), and let the callback function get called with json data. You define the callback function in your page (properly namespaced) and put your update logic inside it.
The advantage of dynamic script node callback is that there is no same-domain restriction like in XHR.
For example, your site is www.foobar.com and some webservices are hosted on www.foobarapi.com. you create a script node in runtime with src="http://www.foobarapi.com/baz?a=foo1&b=foo2&callback=foo.bar.baz"
Meanwhile in your page, you have:
foo.bar.baz = function(data) {
// use the data
}
And your backend service, say a php, can look like:
$a=$GET['a'];
$b=$GET['b'];
$callback = $GET['callback'];
$c = someCalc($a, $b);
echo $callback . "({ \"c\" : $c });";
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.