Calling an external html file using JSONP and PHP - javascript

It is possible this question might be a little vague for the liking of many people here, but my knowledge of the topic is vague also, and despite some searching I have not been able to find anywhere online with clear instructions on how to do this although (in my view) it should probably be one of the simpler cross-domain JSONP operations.
I will explain what I am trying to do. I am trying to retrieve the contents of a HTML file on an external server using both JSONP and a PHP script. I have access to the server - my PHP script is as follows:
<?php
$callback = '';
if (isset($_GET['callback']))
{
$callback = filter_var($_GET['callback'], FILTER_SANITIZE_STRING);
}
$html = include($callback);
echo $callback . '('.json_encode($html).');';
?>
Using this it seems that when I type www.myurl.com/myscript.php?callback=filename.html, the correct file is displayed (although, for some reason, the ?callback is duplicated in the address, and the filename is appended to the end of the output displayed...
I have tried a few different scripts for my HTML file but currently have the following...
function request_jsonp(){
var script = document.createElement('script');
var url = 'http://www.myurl.com/myscript.php?callback=filename.html';
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
Now obviously this doesn't work because the output of the PHP script isn't a working function of any sort, but I am not sure of the best way to go about making it one. I would like to somehow wrap the output in something like this:
function DisplayOutput() {
document.getElementById('output').innerHTML = ...external HTML goes here!... ;
}
...but currently I'm really not sure of the best way to do this.
Any help would be very much appreciated.

callback needs to be the name of the callback function. You should generate a unique one each time the function is called.
You should use a second, different query string variable to determine what URI to fetch.
var jsonp_counter = 0;
function request_jsonp(url, callback){
jsonp_counter++;
var callback_name = "jsonp_function_" + jsonp_counter;
window[callback_name] = callback;
var jsonp_url = 'http://www.myurl.com/myscript.php" +
"?callback=" + encodeURIComponent(callback_name) +
"&url=" + encodeURIComponent(url);
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
request_jsonp("filename.html", function (data) {
do_something_with(data);
});

Related

Retrieve URL Parameters Sent Through JQuery .load()

I am not sure if what I'm trying to do is possible or if I'm going about this the right way. In some circumstances I want them to have a GET parameter as part of the URL. I want the receiving page to be able to differentiate whether the sending load has a parameter or not and adjust accordingly.
Here is what I have that is sending the load:
$(document).ready(function () {
$("a").click(function () {
$("div.pageContent").html('');
$("div.pageContent").load($(this).attr('href'));
return false;
});
});
In this case, the load could have "example.php" or "example.php?key=value". In looking around (primarily on this site), I've found things that seem to be close, but don't quite get there. In the page that is getting loaded (example.php), I have the following:
function $_GET(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if (results == null)
return "";
else
return results[1];
}
$(document).ready(function () {
var URL = "example2.php";
if ($_GET('key'))
{
URL = "example2.php?key=" + $_GET('key');
URL = URL.split(' ').join('%20');
}
$("div.output").load(URL);
});
If the sending source includes a query string, I want to add that to the URL and load it in a div that is unique to this page, otherwise I want to just load it as is without the query string. The big issue I'm running into (I believe) is since this is coming from an AJAX call, the "window.location.href" is not what was sent from the JQuery but rather the URL of the root page which never changes. Is there a way to be able to know what the full URL is that was sent from the load() in the first page by the second one?
Thank you in advance for your help.
I realized that the GET parameters were getting passed as I could access them through php without issue. I didn't know that I could insert php code into a javascript block but once I tried it, all worked out. My new code looks like this:
$(document).ready(function () {
var URL = "example2.php";
var myValue = "<?php echo $_GET['key']; ?>";
if (myValue !== "")
{
URL = "example2.php?key=" + myValue;
URL = URL.split(' ').join('%20');
}
$("div.output").load(URL);
});
I was able to get rid of the GET function out of javascript entirely. I probably made this much more difficult from the start but hopefully it can help someone else in the future.

create callback API

New Restful API's like Google, OpenStreetview use a simple call back mechanism.
Basically you call the API, adding a parameter &callback=my function.
When executing a call to this API, as a result my function is called passing a JSON dataset.
I am trying to create the same mechanisme for a API I am building for my personal use.
As far as I understood my API needs to return a javascript, that calls the function that is passed in a script.
For a test I created this:
function apiCall(URL,values, keyPair,cBackPair) {
// URL specifics URL to call
// keyPair: <keyname>=<key>; leave black if unneeded
// cBacPair: <callBackParametername>=<functionname>
// called is: URL?values&keypair&cBackPair
var request = (keyPair)?'&'+keyPair:'';
request = URL + '?'+ encodeURI(values) + request + '&' + cBackPair;
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", request);
document.body.appendChild(script);
}
function callAPI() {
apiCall('http://xllent.nl/map/ajax/answer.php','q=one','','s=doit');
}
function doit(result) {
alert(result);
}
To test I call callAPI onload.
The script answer.php is very basic:
<?$s = $_GET['s'];
?>
<script type="text/javascript">
doit('jeroen');
</script>
Later the script would use $s to call the right script, and of course supply user data.
For now I am just trying to get the script doit('jeroen'); to be run. But nothing happens.
Typing javascript:doit('jeroen'); in the browser window gives the result I would expect.
Any suggestions?
Don't surround your javascript with <script> tags. You are not generating a HTML file with a javascript body.. You should think of this as if you're generating a javascript file on fly.
Javascript files also don't start and end with <script>

PHP var->Javascript->PHP

I'm working on a project that has the following problem:
The database gives(via php) an array with a list of JavaScript files that need to be loaded. it is stored in the variable $array(php). I need to extract those source files with php(foreach loop) and load them via JavaScript. It is like this:
document.write("<?php foreach($js_files as $filename) {if( trim($filename) <> "" ){echo '<script type=\'text/javascript\' src=$filename></script> \n';}} ?> ");
The problem is that it loads a couple of files but goes wrong with the first one(a google api file). Does anyone have a sollution to this? Or any ideas in which direction i have to look.
This is a bad idea on multiple levels, but can be fairly easily resolved. But first:
1) Never use document.write(). To dynamically load a script it is better to use:
var script = document.createElement('script'); //create a script element
script.src = 'javascript.js'; //path to src file
//now get the body element and append the new script element
document.getElementsByTagName('body')[0].appendChild(script);
2) Loading scripts like this will likely not work if they need to be loaded in a particular order, as the downloading of dynamic scripts occurs asynchronously (non-deterministic)
3) Generally speaking, you should concatenate your js files to reduce http requests, you can use a tool like grunt to make an automatic build process.
4) If you really, really want those scripts to be dynamically loaded though, you can use the process I outlined in (1) to get the file names use ajax:
//depends on jQuery, but could be written vanilla if needed
$.get('myPhp.php', function(resp){
var arr = resp.split(','); //splits returned string on the comma
var i = arr.length;
//iterate through the results set
while (i--) {
//do process from (1) above
}
});
Note that this will still have the unordered problem. If you need sequential dynamic loading check out something like require.js
If the code needs to be fired from a JavaScript function then you can get rid of the document.write, in favor of creating new script objects, and appending to the head tag.
<?php
foreach($js_files as $filename){
if(trim($filename) != ''){
echo 'var s = document.createElement("script");';
echo 's.type = "text/javascript";';
echo 's.src = "' . $filename . '";';
echo 'document.getElementsByTagName("head")[0].appendChild(s);'
}
}
?>
You have to escape the code "" in if( trim($filename) <> "" ) because the " breaks the javascript string.

Handle Malformed Remote JSONP Response

this is a continuation of my original question here link
You can see through my rather lengthy conversion with aaronfrost that we determined the jquery was loading in the .php (as seen on the network tab in CHROME) however it's trying to be ran as a script immediately. My question is where or not it's possible to load that in as plain text and simply then do a js parse out the needed data. Doesn't have to be jQuery this was just the route we were going in this example. I've also tried with the following code and recieve the exact same "Unexpected token" error. I think if there were a way to just some how handle the malformed JSON client side we would be able to make this work, in a ugly sort of way.
If javascript doesn't work do you think going the route of a java applet (preserve client cookies, non-server side) would achieve the desired end result i'm looking for?
<script type="application/javascript" src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script>
<script type="application/javascript">
var url = 'http://www.makecashnow.mobi/jsonp_test.php';
//<!-[CDATA[
function JSONscriptRequest(fullUrl) {
// REST request path
this.fullUrl = fullUrl;
// Keep IE from caching requests
//this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
// Get the DOM location to put the script tag
this.headLoc = document.getElementsByTagName("head").item(0);
// Generate a unique script tag id
this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
}
// Static script ID counter
JSONscriptRequest.scriptCounter = 1;
// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {
// Create the script tag
this.scriptObj = document.createElement("script");
// Add script object attributes
this.scriptObj.setAttribute("type", "text/javascript");
this.scriptObj.setAttribute("charset", "utf-8");
//this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
this.scriptObj.setAttribute("src", this.fullUrl);
this.scriptObj.setAttribute("id", this.scriptId);
}
// removeScriptTag method
//
JSONscriptRequest.prototype.removeScriptTag = function () {
// Destroy the script tag
this.headLoc.removeChild(this.scriptObj);
}
// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
// Create the script tag
this.headLoc.appendChild(this.scriptObj);
}
var obj = new JSONscriptRequest(url);
obj.buildScriptTag();
obj.addScriptTag();
//]]>
</script>

javascript read file workaround (to view script but not load it)

EDIT My question was misleading in that it sounded like I wanted to read/write to the client machine when what I meant was that i want to read a script, not load it, from the source computer. I just assumed since you can summon (load) a script like so
<script LANGUAGE="javascript" SRC="source.js"></script>
Then there must be some way to read source.js before, during or after loading it. I ask because I am still trying to find an answer to my previous question here. I am trying to find some way to make an object/function/class aware of the code that gave rise to it, with comments and tabs and all.
you could load it via ajax and access it as a string
$.ajax({
type: "GET",
dataType: "text",
url: "jsLoader.php",
success: function(data){
alert("Length: " + data.length.toString());
eval(data);
}
});
Or:
$.ajax({
type: "GET",
dataType: "text",
url: "source.js",
success: function(data){
alert("Length: " + data.length.toString());
$("head").append('<script type="text/javascript">' + data + '</script>');
}
});
your question is kind of confusing, but it sounds like you want a way of accessing an object's code. To be honest I don't know how far you can get with this approach, and it won't include comments, but you can always just use toString().
e.g.
function myFunc() {
var somestuff = "my function's code";
};
function myClass() {
var that = this;
this.classFunc = function() {
var somethingelse = "my class function's code";
}
}
alert(myFunc.toString() + '\n\n' + myClass.toString());
Maybe I'm a little confused by your question, but first things first:
<script LANGUAGE="javascript" SRC="source.js"></script>
Does NOT read from client's machine, it reads from the web context that the page was loaded from. If the html page you're loading is www.google.com for example, then src="source.js" will load www.google.com/source.js
If I understand your question correctly though, I think the answer to your questions is that source.js does NOT get read asynchronously in the loading of the web page. Let's say source.js contains only this line.
var variable = {};
In index.html, you have this:
<script type="text/javascript">
alert(typeof(variable));
</script>
<script type="text/javascript" src="source.js"></script>
<script type="text/javascript">
alert(typeof(variable));
</script>
Then, the first alert is going to give you "undefined", and the second alert will give you "object". So, if you want to test if source.js is loaded or not, you can simply do a quick conditional:
if (typeof(variable) != "undefined") { doSomething(); }
One way to get around this would be to setup a php script which fetches the code serverside, wraps it in a function/object, and while doing so assigns the code as a string variable, somewhat like so
/*Get js script at $filename*/
$script = fread($handle, filesize($fileName));
/*Add the code as a string*/
$codeAsString = file_get_contents($fileName);
$script .= '_code=' . json_encode($codeAsString) . ';';
But this doesn't solve the bigger problem of not being able to debug the code. The reason for this is that I am using eval rather than including the scripts. The former executes the code, whereas the latter updates the DOM then executes the code. Only the latter will provide useful debugging info (see here).

Categories