Is there a JavaScript way to do file_get_contents()? - php

Here is the PHP documentation
Here is how I would use it in an Ajax call, if I don't find a pure client way to do this.
$homepage = file_get_contents('http://www.example.com/');
echo $homepage;
Is there way to do this client side instead so I don't have to ajax the string over?

you could do
JS code:
$.post('phppage.php', { url: url }, function(data) {
document.getElementById('somediv').innerHTML = data;
});
PHP code:
$url = $_POST['url'];
echo file_get_contents($url);
That would get you the contents of the url.

It's 2020 and some modern approach;
async function file_get_contents(uri, callback) {
let res = await fetch(uri),
ret = await res.text();
return callback ? callback(ret) : ret; // a Promise() actually.
}
file_get_contents("https://httpbin.org/get", console.log);
// or
file_get_contents("https://httpbin.org/get").then(ret => console.log(ret));

JavaScript cannot go out and scrape data off of pages. It can make a call to a local PHP script that then goes on its behalf and grabs the data, but JavaScript (in the browser) cannot do this.
$.post("/localScript.php", { srcToGet: 'http://example.com' }, function(data){
/* From within here, data is whatever your local script sent back to us */
});
You have options like JSONP and Cross-Origin Resource Sharing at your disposal, but both of those require setting up the other end, so you cannot just choose a domain and start firing off requests for data.
Further Reading: Same origin policy

This function will return the file as a string just like the PHP file_get_contents().
function file_get_contents(uri, callback) {
fetch(uri).then(res => res.text()).then(text => callback(text));
}
However unlike PHP, JavaScript will go on to the next statement, not waiting for the data to return.

Not in a general sense. Cross-domain restrictions disallow Javascript code from doing this.
If the target site has CORS (cross-origin resource sharing) set up, you can use XMLHttpRequest to load files. Most sites do not, as it's off by default for security reasons, and is rarely necessary.
If you just need to include an HTML page, you can stick it in an <iframe> element. This is subject to some layout gotchas, though (the page ends up in a fixed-size element).

Or You can use php.js library. Which allow some php functions for javascript. file_get_contents() function one of them.
<script>
var data = file_get_contents('Your URL');
</script>
You can find more info about php.js : http://phpjs.org/

I think this may be useful for you:
An npm package with the "file-get-contents" method for node.js
https://www.npmjs.com/package/file-get-contents
It is asynchronous so if you are using express it should be used like this
app.get('/', async (req, res)=>{
//paste here the code below
}
Example
const fileGetContents = require('file-get-contents');
// A File request
try {
let data = await fileGetContents('/tmp/foo/bar');
console.log(data);
} catch (err) {
console.log('Unable to load data from /tmp/foo/bar');
}
// Or a HTTP(S) request
fileGetContents('https://pokeapi.co/api/v2/pokemon/1/').then(json => {
const pokemon = JSON.parse(json);
console.log(`Name of first pokemon is ${pokemon.name}`);
}).catch(err => {
console.err(`Unable to get content from PokeAPI. Reason: ${err.message}`);
});

<div id="svg">
</div>
<script>
function file_get_contents(uri, callback) {
fetch(uri).then(res => res.text()).then(text =>
{
var xmlSvg =text;
console.log(xmlSvg );
document.getElementById('svg').innerHTML = xmlSvg;
})
}
var uri ='You-urlllllllll-svg';
file_get_contents(uri);
</script>

function file_get_contents(filename) {
fetch(filename).then((resp) => resp.text()).then(function(data) {
document.getElementById("id").innerHTML = data;
});
}
file_get_contents("url");
<span id="id"></span>

Related

Download file instead showing it it new tab [duplicate]

I have a jquery-based single-page webapp. It communicates with a RESTful web service via AJAX calls.
I'm trying to accomplish the following:
Submit a POST that contains JSON data to a REST url.
If the request specifies a JSON response, then JSON is returned.
If the request specifies a PDF/XLS/etc response, then a downloadable binary is returned.
I have 1 & 2 working now, and the client jquery app displays the returned data in the web page by creating DOM elements based on the JSON data. I also have #3 working from the web-service point of view, meaning it will create and return a binary file if given the correct JSON parameters. But I'm unsure the best way to deal with #3 in the client javascript code.
Is it possible to get a downloadable file back from an ajax call like this? How do I get the browser to download and save the file?
$.ajax({
type: "POST",
url: "/services/test",
contentType: "application/json",
data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
dataType: "json",
success: function(json, status){
if (status != "success") {
log("Error loading data");
return;
}
log("Data loaded!");
},
error: function(result, status, err) {
log("Error loading data");
return;
}
});
The server responds with the following headers:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
Another idea is to generate the PDF and store it on the server and return JSON that includes a URL to the file. Then, issue another call in the ajax success handler to do something like the following:
success: function(json,status) {
window.location.href = json.url;
}
But doing that means I would need to make more than one call to the server, and my server would need to build downloadable files, store them somewhere, then periodically clean up that storage area.
There must be a simpler way to accomplish this. Ideas?
EDIT: After reviewing the docs for $.ajax, I see that the response dataType can only be one of xml, html, script, json, jsonp, text, so I'm guessing there is no way to directly download a file using an ajax request, unless I embed the binary file in using Data URI scheme as suggested in the #VinayC answer (which is not something I want to do).
So I guess my options are:
Not use ajax and instead submit a form post and embed my JSON data into the form values. Would probably need to mess with hidden iframes and such.
Not use ajax and instead convert my JSON data into a query string to build a standard GET request and set window.location.href to this URL. May need to use event.preventDefault() in my click handler to keep browser from changing from the application URL.
Use my other idea above, but enhanced with suggestions from the #naikus answer. Submit AJAX request with some parameter that lets web-service know this is being called via an ajax call. If the web service is called from an ajax call, simply return JSON with a URL to the generated resource. If the resource is called directly, then return the actual binary file.
The more I think about it, the more I like the last option. This way I can get information back about the request (time to generate, size of file, error messages, etc.) and I can act on that information before starting the download. The downside is extra file management on the server.
Any other ways to accomplish this? Any pros/cons to these methods I should be aware of?
letronje's solution only works for very simple pages. document.body.innerHTML += takes the HTML text of the body, appends the iframe HTML, and sets the innerHTML of the page to that string. This will wipe out any event bindings your page has, amongst other things. Create an element and use appendChild instead.
$.post('/create_binary_file.php', postData, function(retData) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", retData.url);
iframe.setAttribute("style", "display: none");
document.body.appendChild(iframe);
});
Or using jQuery
$.post('/create_binary_file.php', postData, function(retData) {
$("body").append("<iframe src='" + retData.url+ "' style='display: none;' ></iframe>");
});
What this actually does: perform a post to /create_binary_file.php with the data in the variable postData; if that post completes successfully, add a new iframe to the body of the page. The assumption is that the response from /create_binary_file.php will include a value 'url', which is the URL that the generated PDF/XLS/etc file can be downloaded from. Adding an iframe to the page that references that URL will result in the browser promoting the user to download the file, assuming that the web server has the appropriate mime type configuration.
I've been playing around with another option that uses blobs. I've managed to get it to download text documents, and I've downloaded PDF's (However they are corrupted).
Using the blob API you will be able to do the following:
$.post(/*...*/,function (result)
{
var blob=new Blob([result]);
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="myFileName.txt";
link.click();
});
This is IE 10+, Chrome 8+, FF 4+. See https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL
It will only download the file in Chrome, Firefox and Opera. This uses a download attribute on the anchor tag to force the browser to download it.
I know this kind of old, but I think I have come up with a more elegant solution. I had the exact same problem. The issue I was having with the solutions suggested were that they all required the file being saved on the server, but I did not want to save the files on the server, because it introduced other problems (security: the file could then be accessed by non-authenticated users, cleanup: how and when do you get rid of the files). And like you, my data was complex, nested JSON objects that would be hard to put into a form.
What I did was create two server functions. The first validated the data. If there was an error, it would be returned. If it was not an error, I returned all of the parameters serialized/encoded as a base64 string. Then, on the client, I have a form that has only one hidden input and posts to a second server function. I set the hidden input to the base64 string and submit the format. The second server function decodes/deserializes the parameters and generates the file. The form could submit to a new window or an iframe on the page and the file will open up.
There's a little bit more work involved, and perhaps a little bit more processing, but overall, I felt much better with this solution.
Code is in C#/MVC
public JsonResult Validate(int reportId, string format, ReportParamModel[] parameters)
{
// TODO: do validation
if (valid)
{
GenerateParams generateParams = new GenerateParams(reportId, format, parameters);
string data = new EntityBase64Converter<GenerateParams>().ToBase64(generateParams);
return Json(new { State = "Success", Data = data });
}
return Json(new { State = "Error", Data = "Error message" });
}
public ActionResult Generate(string data)
{
GenerateParams generateParams = new EntityBase64Converter<GenerateParams>().ToEntity(data);
// TODO: Generate file
return File(bytes, mimeType);
}
on the client
function generate(reportId, format, parameters)
{
var data = {
reportId: reportId,
format: format,
params: params
};
$.ajax(
{
url: "/Validate",
type: 'POST',
data: JSON.stringify(data),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: generateComplete
});
}
function generateComplete(result)
{
if (result.State == "Success")
{
// this could/should already be set in the HTML
formGenerate.action = "/Generate";
formGenerate.target = iframeFile;
hidData = result.Data;
formGenerate.submit();
}
else
// TODO: display error messages
}
There is a simplier way, create a form and post it, this runs the risk of resetting the page if the return mime type is something that a browser would open, but for csv and such it's perfect
Example requires underscore and jquery
var postData = {
filename:filename,
filecontent:filecontent
};
var fakeFormHtmlFragment = "<form style='display: none;' method='POST' action='"+SAVEAS_PHP_MODE_URL+"'>";
_.each(postData, function(postValue, postKey){
var escapedKey = postKey.replace("\\", "\\\\").replace("'", "\'");
var escapedValue = postValue.replace("\\", "\\\\").replace("'", "\'");
fakeFormHtmlFragment += "<input type='hidden' name='"+escapedKey+"' value='"+escapedValue+"'>";
});
fakeFormHtmlFragment += "</form>";
$fakeFormDom = $(fakeFormHtmlFragment);
$("body").append($fakeFormDom);
$fakeFormDom.submit();
For things like html, text and such, make sure the mimetype is some thing like application/octet-stream
php code
<?php
/**
* get HTTP POST variable which is a string ?foo=bar
* #param string $param
* #param bool $required
* #return string
*/
function getHTTPPostString ($param, $required = false) {
if(!isset($_POST[$param])) {
if($required) {
echo "required POST param '$param' missing";
exit 1;
} else {
return "";
}
}
return trim($_POST[$param]);
}
$filename = getHTTPPostString("filename", true);
$filecontent = getHTTPPostString("filecontent", true);
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename\"");
echo $filecontent;
It is been a while since this question was asked but I had the same challenge and want to share my solution. It uses elements from the other answers but I wasn't able to find it in its entirety. It doesn't use a form or an iframe but it does require a post/get request pair. Instead of saving the file between the requests, it saves the post data. It seems to be both simple and effective.
client
var apples = new Array();
// construct data - replace with your own
$.ajax({
type: "POST",
url: '/Home/Download',
data: JSON.stringify(apples),
contentType: "application/json",
dataType: "text",
success: function (data) {
var url = '/Home/Download?id=' + data;
window.location = url;
});
});
server
[HttpPost]
// called first
public ActionResult Download(Apple[] apples)
{
string json = new JavaScriptSerializer().Serialize(apples);
string id = Guid.NewGuid().ToString();
string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
System.IO.File.WriteAllText(path, json);
return Content(id);
}
// called next
public ActionResult Download(string id)
{
string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
string json = System.IO.File.ReadAllText(path);
System.IO.File.Delete(path);
Apple[] apples = new JavaScriptSerializer().Deserialize<Apple[]>(json);
// work with apples to build your file in memory
byte[] file = createPdf(apples);
Response.AddHeader("Content-Disposition", "attachment; filename=juicy.pdf");
return File(file, "application/pdf");
}
In short, there is no simpler way. You need to make another server request to show PDF file. Al though, there are few alternatives but they are not perfect and won't work on all browsers:
Look at data URI scheme. If binary data is small then you can perhaps use javascript to open window passing data in URI.
Windows/IE only solution would be to have .NET control or FileSystemObject to save the data on local file system and open it from there.
Not entirely an answer to the original post, but a quick and dirty solution for posting a json-object to the server and dynamically generating a download.
Client side jQuery:
var download = function(resource, payload) {
$("#downloadFormPoster").remove();
$("<div id='downloadFormPoster' style='display: none;'><iframe name='downloadFormPosterIframe'></iframe></div>").appendTo('body');
$("<form action='" + resource + "' target='downloadFormPosterIframe' method='post'>" +
"<input type='hidden' name='jsonstring' value='" + JSON.stringify(payload) + "'/>" +
"</form>")
.appendTo("#downloadFormPoster")
.submit();
}
..and then decoding the json-string at the serverside and setting headers for download (PHP example):
$request = json_decode($_POST['jsonstring']), true);
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Pragma: no-cache');
$scope.downloadSearchAsCSV = function(httpOptions) {
var httpOptions = _.extend({
method: 'POST',
url: '',
data: null
}, httpOptions);
$http(httpOptions).then(function(response) {
if( response.status >= 400 ) {
alert(response.status + " - Server Error \nUnable to download CSV from POST\n" + JSON.stringify(httpOptions.data));
} else {
$scope.downloadResponseAsCSVFile(response)
}
})
};
/**
* #source: https://github.com/asafdav/ng-csv/blob/master/src/ng-csv/directives/ng-csv.js
* #param response
*/
$scope.downloadResponseAsCSVFile = function(response) {
var charset = "utf-8";
var filename = "search_results.csv";
var blob = new Blob([response.data], {
type: "text/csv;charset="+ charset + ";"
});
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename); // #untested
} else {
var downloadContainer = angular.element('<div data-tap-disabled="true"><a></a></div>');
var downloadLink = angular.element(downloadContainer.children()[0]);
downloadLink.attr('href', window.URL.createObjectURL(blob));
downloadLink.attr('download', "search_results.csv");
downloadLink.attr('target', '_blank');
$document.find('body').append(downloadContainer);
$timeout(function() {
downloadLink[0].click();
downloadLink.remove();
}, null);
}
//// Gets blocked by Chrome popup-blocker
//var csv_window = window.open("","","");
//csv_window.document.write('<meta name="content-type" content="text/csv">');
//csv_window.document.write('<meta name="content-disposition" content="attachment; filename=data.csv"> ');
//csv_window.document.write(response.data);
};
I think the best approach is to use a combination, Your second approach seems to be an elegant solution where browsers are involved.
So depending on the how the call is made. (whether its a browser or a web service call) you can use a combination of the two, with sending a URL to the browser and sending raw data to any other web service client.
Found it somewhere long time ago and it works perfectly!
let payload = {
key: "val",
key2: "val2"
};
let url = "path/to/api.php";
let form = $('<form>', {'method': 'POST', 'action': url}).hide();
$.each(payload, (k, v) => form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v})) );
$('body').append(form);
form.submit();
form.remove();
I have been awake for two days now trying to figure out how to download a file using jquery with ajax call. All the support i got could not help my situation until i try this.
Client Side
function exportStaffCSV(t) {
var postData = { checkOne: t };
$.ajax({
type: "POST",
url: "/Admin/Staff/exportStaffAsCSV",
data: postData,
success: function (data) {
SuccessMessage("file download will start in few second..");
var url = '/Admin/Staff/DownloadCSV?data=' + data;
window.location = url;
},
traditional: true,
error: function (xhr, status, p3, p4) {
var err = "Error " + " " + status + " " + p3 + " " + p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
ErrorMessage(err);
}
});
}
Server Side
[HttpPost]
public string exportStaffAsCSV(IEnumerable<string> checkOne)
{
StringWriter sw = new StringWriter();
try
{
var data = _db.staffInfoes.Where(t => checkOne.Contains(t.staffID)).ToList();
sw.WriteLine("\"First Name\",\"Last Name\",\"Other Name\",\"Phone Number\",\"Email Address\",\"Contact Address\",\"Date of Joining\"");
foreach (var item in data)
{
sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\"",
item.firstName,
item.lastName,
item.otherName,
item.phone,
item.email,
item.contact_Address,
item.doj
));
}
}
catch (Exception e)
{
}
return sw.ToString();
}
//On ajax success request, it will be redirected to this method as a Get verb request with the returned date(string)
public FileContentResult DownloadCSV(string data)
{
return File(new System.Text.UTF8Encoding().GetBytes(data), System.Net.Mime.MediaTypeNames.Application.Octet, filename);
//this method will now return the file for download or open.
}
Good luck.
I liked Frank's idea and decided to do my own twist to it. As trying to do it in one post is very complicated, I'm using the two post method but only hitting the database once and no need to save the file or clean up file when completed.
First I run the ajax request to retrieve the data but instead of returning the data from the controller I will return a GUID that is tied to a TempData storage of the records.
$.get("RetrieveData", { name: "myParam"} , function(results){
window.location = "downloadFile?id=" + results
});
public string RetrieveData(string name)
{
var data = repository.GetData(name);
string id = Guid.NewGuid().ToString();
var file = new KeyValuePair<string, MyDataModel>(name, data);
TempData[id]=file;
return id;
}
Then when I call the window.location I pass the Guid to the new method and get the data from TempData. After this method is executed TempData will be free.
public ActionResult DownloadFile(string id)
{
var file = (KeyValuePair<string,MyDataModel>)TempData[id];
var filename = file.Key;
var data = file.Value;
var byteArray = Encoding.UTF8.GetBytes(data);
...
return File(byteArray, "text/csv", "myFile.csv");
}
Another approach instead of saving the file on the server and retrieving it, is to use .NET 4.0+ ObjectCache with a short expiration until the second Action (at which time it can be definitively dumped). The reason that I want to use JQuery Ajax to do the call, is that it is asynchronous. Building my dynamic PDF file takes quite a bit of time, and I display a busy spinner dialog during that time (it also allows other work to be done). The approach of using the data returned in the "success:" to create a Blob does not work reliably. It depends on the content of the PDF file. It is easily corrupted by data in the response, if it is not completely textual which is all that Ajax can handle.
Solution
Content-Disposition attachment seems to work for me:
self.set_header("Content-Type", "application/json")
self.set_header("Content-Disposition", 'attachment; filename=learned_data.json')
Workaround
application/octet-stream
I had something similar happening to me with a JSON, for me on the server side I was setting the header to
self.set_header("Content-Type", "application/json")
however when i changed it to:
self.set_header("Content-Type", "application/octet-stream")
It automatically downloaded it.
Also know that in order for the file to still keep the .json suffix you will need to it on filename header:
self.set_header("Content-Disposition", 'filename=learned_data.json')
The Problems with Making your own events
Many of the solutions proposed on this article have the JavaScript run asynchronously and create a link element then calling
const a = documet.createElement("a")
a.click()
or creating a mouse event
new MouseEvent({/* ...some config */})
This would seem fine right? What could be wrong with this?
What is an Event-Sourcing?
Event sourcing has a bunch of meanings across computing such as a system of pub sub in a cloud based architecture, or the browser api EventSource. In the context of a browser
all events have a source and that source has hidden property that says who initiated this event (the user or the site).
Knowing this we can start to understand why two click events might not be treated the same
user click* new MouseEvent()
----------- -----------
| Event 1 | | Event 2 |
----------- -----------
| |
|----------------------|
|
|
----------------------
| Permissions Policy | Available in chrome allows the server to control
---------------------- what features are going to be used by the JS
|
|
----------------------------
| Browser Fraud Protection | The Browser REALLY doesnt like being told to pretend
---------------------------- to be a user. If you will remember back to the early
| 2000s when one click spun off 2000 pop ups. Well here
| is where popups are blocked, fraudulent ad clicks are
\ / thrown out, and most importantly for our case stops
v fishy downloads
JavaScript Event Fires
So I just Can't Download off A POST That's Dumb
No, of course you can. You just need to give the user a chance to create the event. Here are a number of patterns that you can use to create user flows that are obvious and convectional and will not be flagged as fraud. (using jsx sorry not sorry)
A Form can be used to navigate to a url with a post action.
const example = () => (
<form
method="POST"
action="/super-api/stuff"
onSubmit={(e) => {/* mutably change e form data but don't e.preventDetfault() */}}
>
{/* relevant input fields of your download */}
</form>
)
Preloading If your download is non-configurable you may want to consider preloading the download into resp.blob() or new Blob(resp) this tells the browser that this is a file and we wont be doing any string operations on it. As with the other answers you can use window.URL.createObjectURL what is not mentioned is that
createObjectURL CAN MAKE A MEMORY LEAK IN JAVASCRIPTsource
If you don't want the C++ bully's to come make fun of you you must free this memory. Ahh but I'm just a hobbiest who loves his garbage collector. Have no fear this is very simple if you are working in most frameworks (for me react) you just register some sort of clean up effect on your component and your right as rain.
const preload = () => {
const [payload, setPayload] = useState("")
useEffect(() => {
fetch("/super-api/stuff")
.then((f) => f.blob())
.then(window.URL.createObjectURL)
.then(setPayload)
return () => window.URL.revokeObjectURL(payload)
}, [])
return (<a href={payload} download disabled={payload === ""}>Download Me</a>)
}
I think I got close, but something is corrupting the file (Image), any way, maybe some one can disclose the problem of this approach
$.ajax({
url: '/GenerateImageFile',
type: 'POST',
cache: false,
data: obj,
dataType: "text",
success: function (data, status, xhr) {
let blob = new Blob([data], { type: "image/jpeg" });
let a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = "test.jpg";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.removeObjectURL(a.href);
},
complete: function () {
},
beforeSend: function () {
}
});
With HTML5, you can just create an anchor and click on it. There is no need to add it to the document as a child.
const a = document.createElement('a');
a.download = '';
a.href = urlForPdfFile;
a.click();
All done.
If you want to have a special name for the download, just pass it in the download attribute:
const a = document.createElement('a');
a.download = 'my-special-name.pdf';
a.href = urlForPdfFile;
a.click();

Ajax Method without XMLHttpRequest() Object

I have one query about Ajax methodology. I am used to work with ajax like i use four simple lines written below:
$.ajax({
type: "POST",
url: "/application/group/addMembers",
data: {memberIds: selectedMembers, groupId:<?php echo $this->groupId; ?>},
success: (function(msg) {
// alert(msg);
var ans = JSON.parse(msg);
alert(ans['message']); // msg is array returned from php script in json
})
});
Now, When i study more on different sites or tutorials. They do ajax by creating XMLHTMLREQUEST(), which is used to exchange information with server. And some more things like open, send functions.
But i don't create XMLHTMLREQUEST object and my ajax still works fine. I just want to know the difference. Do i lose something when i don't communicate with server using XMLHTMLREQUEST object. I did search on it. But i still need an answer.
the difference between your four simple line and XMLHttpRequest() is the language itself where XMLHttpRequest() is pure javascript while your code above is jquery.
infact you could ignore both and use jQuery.get() & jQuery.load() as they are higher-level alternatives and easier to use. If less common options are required, though, $.ajax() can be used more flexibly.
Different browsers implement AJAX differently (Actually only IE really). jQuery handles all of the cross-browser implementation differences and creates the XHR object in the background.
From jQuery Source code:
jQuery.ajaxSettings.xhr = function() {
try {
return new XMLHttpRequest();
} catch( e ) {}
};
var xhrSupported = jQuery.ajaxSettings.xhr(),
xhrSuccessStatus = {
// file protocol always yields status code 0, assume 200
0: 200,
// Support: IE9
// #1450: sometimes IE returns 1223 when it should be 204
1223: 204
},
// Support: IE9
// We need to keep track of outbound xhr and abort them manually
// because IE is not smart enough to do it all by itself
xhrId = 0,
xhrCallbacks = {};
if ( window.ActiveXObject ) {
jQuery( window ).on( "unload", function() {
for( var key in xhrCallbacks ) {
xhrCallbacks[ key ]();
}
xhrCallbacks = undefined;
});
}
jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
jQuery.support.ajax = xhrSupported = !!xhrSupported;

Getting default Server time in jQuery?

How can I get the web-server time using jQuery?
Here's a way that may work without any particular code, or even a valid path, on the server side.
try {
var date = new Date($.ajax({'type': 'HEAD', 'url': '/'}).getResponseHeader('Date'));
}
catch(err) {
var date = null;
}
This is presumptive that the server will always return a "Date" header. Some experimentation with the particulars of your server will be necessary.
EDIT TO ADD: Note that this is more of a cutesy hackish way to do this. The "correct" way would be to set up a server-side script to return the server time quickly, or possibly put it inline to the page where the script will be running, or simply use the client-side time if it would be "good enough."
To get server code, you'll need to have some method on server-side that would either add time to the page while rendering, or if you need real-time time (ops), you need to make an ajax call to server using jQuery.
That means that you need to have something on server side that would respond to ajax request. What language are you using for server side?
If you've got something like php running on your server you could just put something like this to set the date/time by embedding it into the script:
<script>
var date = new Date("<?php echo date("Y-m-d H:i:s"); ?>");
alert(date);
</script>
used Garrett answer, but $.ajax has a short response time, which means its 'getResponseHeader' method cannot be called immediately.
I think this can be a fix:
var Date1 = null;
var endInterval;
function DoJob() {
if (Date1 == null) {
if (endInterval)
clearInterval(endInterval);
endInterval = setInterval(DoJob, 100);
return;
}
/*
job to do...
*/
if (endInterval)
clearInterval(endInterval);
}
try {
var oHead = $.ajax({ 'type': 'HEAD', 'url': '/' }).success(function () {
Date1 = new Date(oHead.getResponseHeader('Date'));
});
}
catch (err) {
Date1 = null;
}
DoJob();

Reverse Ajax implementation using php

I am looking to implement reverse ajax in my application which is using PHP and jquery. I have googled a bit about it and found XAJA but that seems to be a paid application. Is there an open source application available for the same or has someone implemented it?
Some pointers or hints would be very helpful.
Thanks in advance.
I know of two types of reverse AJAX:
1- Polling
2- Pushing
I think polling is rather easier to implement, you just have your javascript make a regular request to the server every time interval, and when the server have some data for it it will respond. Its like a ping and some call it heartbeat, but its the very obvious solution for this problem. However it may easily overload the server.
EDIT Simple polling Example code:
Server-Side:
<?php
//pong.php php isn't my main thing but tried my best!
$obj = new WhatsNew();
$out = "";
if ($obj->getGotNew()){
$types = new array();
foreach ($obj->newStuff() as $type)
{
$new = array('type' => $type);
$types[] = $new;
}
$out = json_encode($types);
}
else{
$out = json_encode(array('nothingNew' => true));
}
Client-Side:
function ping(){
$.ajax(
{
url : "pong.php",
success : function (data){
data = JSON.parse(data),
if (data['nothingNew'])
return;
for(var i in data){
var type = data[i]['type'];
if (type && incomingDataHandlers[type]){
incomingDataHandlers[type]();
}
}
});
}
incomingDataHandlers = {
comments: function () {
$.ajax({
url: "getComments.php",
method: "GET",
data: getNewCommentRequsetData() // pass data to the server;
success : function (data){
//do something with your new comments
}
});
},
message: function (){
$.ajax({
url: "getMessages.php",
method: "GET",
data: getNewMessageRequestData() // pass data to the server;
success : function (data){
//do something with your new messages
}
});
}
}
$(docment).ready(function () {
setInterval(ping, 1000);
})
You are looking for what they call "long poll" - I did a "long poll php" and I got this thread on stack overflow:
How do I implement basic "Long Polling"?
you could websockets in conjuction with "flash" websockets because almost all browser have flash on board(average around 96%? => http://www.statowl.com/flash.php) => https://github.com/gimite/web-socket-js. You could use this together with http://code.google.com/p/phpwebsocket/. Still I am wondering if the performance is going to be any good. If it all possible I would use node.js to do reverse ajax. http://socket.io is a really cool project to do this!
Have you checked APE ?
Its a push based real-time data streaming technology over a single low volume ajax connection. The concept is useful, you may be able to replicate the same thing with your server-side implementation

Getting json on Ajax response callback

I am trying to create a little ajax chat system (just for the heck of it) and I am using prototype.js to handle the ajax part.
One thing I have read in the help is that if you return json data, the callback function will fill that json data in the second parameter.
So in my php file that gets called I have:
header('Content-type: application/json');
if (($response = $acs_ajch_sql->postmsg($acs_ajch_msg,$acs_ajch_username,$acs_ajch_channel,$acs_ajch_ts_client)) === true)
echo json_encode(array('lastid' => $acs_ajch_sql->msgid));
else
echo json_encode(array('error' => $response));
On the ajax request I have:
onSuccess: function (response,json) {
alert(response.responseText);
alert(json);
}
The alert of the response.responseText gives me {"lastid": 8 } but the json gives me null.
Anyone know how I can make this work?
This is the correct syntax for retrieving JSON with Prototype
onSuccess: function(response){
var json = response.responseText.evalJSON();
}
There is a property of Response: Response.responseJSON which is filled with a JSON objects only if the backend returns Content-Type: application/json, i.e. if you do something like this in your backend code:
$this->output->set_content_type('application/json');
$this->output->set_output(json_encode($answer));
//this is within a Codeigniter controller
in this case Response.responseJSON != undefined which you can check on the receiving end, in your onSuccess(t) handler:
onSuccess:function(t) {
if (t.responseJSON != undefined)
{
// backend sent some JSON content (maybe with error messages?)
}
else
{
// backend sent some text/html, let's say content for my target DIV
}
}
I am not really answering the question about the second parameter of the handler, but if it does exist, for sure Prototype will only provide it in case of proper content type of the response.
This comes from Prototype official :
Evaluating a JavaScript response
Sometimes the application is designed
to send JavaScript code as a response.
If the content type of the response
matches the MIME type of JavaScript
then this is true and Prototype will
automatically eval() returned code.
You don't need to handle the response
explicitly if you don't need to.
Alternatively, if the response holds a
X-JSON header, its content will be
parsed, saved as an object and sent to
the callbacks as the second argument:
new Ajax.Request('/some_url', {
method:'get', onSuccess:
function(transport, json){
alert(json ? Object.inspect(json) : "no JSON object");
}
});
Use this functionality when you want to fetch non-trivial
data with Ajax but want to avoid the
overhead of parsing XML responses.
JSON is much faster (and lighter) than
XML.
You could also just skip the framework. Here's a cross-browser compatible way to do ajax, used in a comments widget:
//fetches comments from the server
CommentWidget.prototype.getComments = function() {
var commentURL = this.getCommentsURL + this.obj.type + '/' + this.obj.id;
this.asyncRequest('GET', commentURL, null);
}
//initiates an XHR request
CommentWidget.prototype.asyncRequest = function(method, uri, form) {
var o = createXhrObject()
if(!o) { return null; }
o.open(method, uri, true);
o.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
var self = this;
o.onreadystatechange = function () {self.callback(o)};
if (form) {
o.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
o.send(makePostData(form));
} else {
o.send('');
}
}
//after a comment is posted, this rewrites the comments on the page
CommentWidget.prototype.callback = function(o) {
if (o.readyState != 4) { return }
//turns the JSON string into a JavaScript object.
var response_obj = eval('(' + o.responseText + ')');
this.comments = response_obj.comments;
this.refresh()
}
I open-sourced this code here http://www.trailbehind.com/comment_widget

Categories