Generate save as dialog box with AJAX request in Ext Js - ajax

I have an application that contains a grid and button for the user to be able to export the grid to excel. I want to be able to show the save as dialog box when the server responds with the excel file.The server accepts the parameters as a JSON object. Here is my code:-
Ext.Ajax.request({
url: '/export/excel/',
method: 'POST',
//Send the query as the message body
jsonData: jsonStr,
success: function (result,request) {
Ext.DomHelper.append(document.body, {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
//src:result,
css: 'display:none;visibility:hidden;height:1px;'
});
}, //success
failure: function (response, opts) {
var msg = 'server-side failure with status code: ' + response.status + ' message: ' + response.statusText;
Ext.Msg.alert('Error Message', msg);
}
});
I know there is a similar question ( ExtJS AJAX save as dialog box) but that references a static file on the server.In my case, depending upon the json sent the result is going to be different each time. I get back the entire excel file that i want in the result.responseText. What needs to be done so that the dialog box popup up asking the user for save as options? Also, im not sure how the src in the domhelper should be configured. Any help would be really appreciated.

I believe the only way to do this in a totally client agnostic way is to force it from the server-side using a Content-Type of: octect-stream and Content-Disposition of 'attachment' with a suggested filename. See:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
and
http://www.ryboe.com/tutorials/php-headers-force-download
You can also use so-called 'dataURIs' but they have their own set of issues:
http://en.wikipedia.org/wiki/Data_URI_scheme
My recommendation would be to return EXCEL content dynamically on the server and just make the button a link to that url that POSTS the current data your working with and sets the correct response headers to trigger your browser to download the file. Since you are doing an AJAX call and not letting the web-browser get the URL directly, any HTTP headers you set to control the way the browser interprets the content won't matter because you are doing it in JS not in the user's browser. By returning the content directly to the user through a link on the server, you'll get around this problem.
Since you actually want the user to click on the link, I don't think AJAX is appropiate here.

I made the server side return the path of the location the file is created and saved, instead of sending the file as an attachment in the response and hence avoiding the problem of setting the headers in the response. Then i just set the source of the iframe in the code to the path that gets returned in the response (result.responseText).

Related

Openseadragon with XML document variable instead of URL?

What is the correct way to open a SeaDragon viewer with straight XML data? I need to know what I'm doing wrong here. I have a bunch of DZI images that are hosted on another domain that I need to display, but I can't do a simple OpenSeadragon() call with the appropriate URLs because the domain the images are on has no "Access-Control-Allow-Origin" header. As such, I've set up a proxy controller to retrieve the XML data and pass that back to my web page. However, I can't get the images to load with the XML data.
I've been using a working image (from a different website) to test the issue and figure out what I need to do. When I use the following code, the image displays:
var viewer = OpenSeadragon({
id: "openseadragon1",
prefixUrl: "../../Scripts/openseadragon/images/",
tileSources: "https://familysearch.org/dz/v1/TH-1971-27860-10353-27/image.xml?ctx=CrxCtxPublicAccess&session"
});
Now I'm trying to display the image the way I am with my Proxy controller, by retrieving the XML and using the XML in my OpenSeadragon call:
var ajaxresult = $.ajax({
url: "https://familysearch.org/dz/v1/TH-1971-27860-10353-27/image.xml?ctx=CrxCtxPublicAccess&session",
type: 'get',
success: function (data) {
// data is an XMLdocument object
var viewer = OpenSeadragon({
id: "openseadragon1",
prefixUrl: "../../Scripts/openseadragon/images/",
tileSources: data
});
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.responseText || textStatus);
}
});
I get a blank image and my console says that every tile failed to load. I have also tried pasting the xml directly into the tileSources field as a string, like this:
tileSources: '<?xml version="1.0" encoding="utf-8"?><Image TileSize="256" Overlap="1" Format="jpg" ServerFormat="Default" xmlns="http://schemas.microsoft.com/deepzoom/2009"> <Size Width="6233" Height="4683" /></Image>'
but that doesn't work either.
What am I doing wrong here?
I found a way to resolve the issue. Because my images were hosted on an S3 account, I discovered that I could log into the account and add CORS configuration to each of the image buckets. So, no need to use Ajax to pull the XML; once I added CORS to the buckets, I was able to put the URLs in the OpenSeadragon call directly.
Unfortunately OpenSeadragon does not yet support passing the XML directly; you'll have to break apart the info. See the answer here:
https://github.com/openseadragon/openseadragon/issues/460

Cross domain call through JSONP

I want to display html pages from external domains but unable to do this through JSONP i.e when page loads,page doesn't contain anything. It just shows a blank page. Please find my code below for reference.
Code:
Ext.util.JSONP.request({
url:wikiurl,
callbackKey:'callback',
params:{},
callback:function(data){
console.log(data);
console.log("inside callback");
},
success:function(result,opts){
console.log(result);
},
failure:function(result,opts){
console.log(result);
}
});
=>what is the URL?
=>who is sending the response, you need to send specific response from server when some one need JASONP data.
=>you are logging everything to console, it wont show in page, probably in firebug console or similar console it would be visible.
=>to see response in page, just dump the data in a div element in page.

Chrome displays ajax response when pressing back button

I've come across a problem that if I use jQuery's Get method to get some content, if I click back, instead of it actually going back one page in the history, it instead shows the content returned by the Ajax query.
Any idea's?
http://www.dameallans.co.uk/preview/allanian-society/news/56/Allanian-test
On the above page, if you use the pagination below the list of comments you will notice when clicking back after changing a page, that it shows the HTML content used to generate the list of comments.
I've noticed it doesn't always do it, but if you click on a different page a few times and click the back button, it simply displays json text within the window instead of the website.
For some reason, this is only affecting Chrome as IE and Firefox work ok.
Make sure your AJAX requests use a different URL from the full HTML documents. Chrome caches the most recent request even if it is just a partial.
https://code.google.com/p/chromium/issues/detail?id=108425
Just in case you are using jQuery with History API (or some library like history.js), you should change $.getJSON to $.ajax with cache set to false:
$.ajax({
dataType: "json",
url: url,
cache: false,
success: function (json) {...}
});
Actually this is the expected behavior of caching system according to specs and not a chrome issue. The cache only differentiate requests base on URL and request method (get, post, ...), not any of the request headers.
But there is a Vary header to tell browser to consider some headers when checking the cache. For example by adding Vary:X-Requested-With to the server response the browser knows that this response vary if request X-Requested-With header is changed. Or by adding Vary:Content-Type to the server response the browser knows that this response vary if request Content-Type header is changed.
You can add this line to your router for PHP:
header('Vary:X-Requested-With');
And use a middleware in node.js:
app.use(function(req, res) {
res.header('Vary', 'X-Requested-With');
});
You can also add a random value to the end of the ajax url. This will ignore the previous chrome cache and will request a new version
url = '/?'+Math.random()
Just add the following header to the Response headers :
Vary: Accept
I couldn't give different urls for each ajax request as it was an ajax pagination, declaring no cache on headers did nothing, so i included a little javascript in the view only when headers were for the ajax request:
<script>
if (typeof jQuery == 'undefined') {
window.location = "<?php echo $this->here; ?>";
}
</script>
It is a dirty trick, but it works, if the ajax content is normally loaded, the container has Jquery loaded so it does nothing. But if you load the ajax supposed content without the surrounding content, Jquery is missing (at least in my case), so i redirect to the current page requesting a normal GET page with all the headers and scripts.
If you put it in the top of the page, the user won't notice because it won't wait till the page loads, it will redirect as soon as the browser gets this 4 lines...
Replace here; ?> by the current url in your APP, this was a CakePhp 2.X
Still had this problem in 2021 in Chrome.
Problem is doing underlying ajax request to the same url as the one the user is currently on.
I was working in Symfony and the complete fix that did the work for me was
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('s-maxage', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
/**
* from https://stackoverflow.com/a/1975677/5418514
*
* The HTTP request header 'Accept' defines the Content-Types a client can process.
* If you have two copies of the same content at the same URL, differing only in Content-Type,
* then using Vary: Accept could be appropriate.
*/
$response->headers->set('Vary', 'Accept');
The #abraham's answer is right.
I just wanted to post a solution for Rails: all you need is just add different path to routes.rb.
In example, I have resource :people and I want to compose index page from ajax parts one of those is list of people. The straightforward way is to create index.js.erb and to load partial via ajax using url: people_path. But here occurs the issue.
So, for Rails, it needs just add a different route, like
get 'people_list', to: 'people#index', as: :people_list, format: :js
If I want to use index method of a laravel controller returns both html and json response, I add a get parameter at the end of the endpoint to pass browser caching:
axios.get(url, {params: {ajax: 1}})

Cannot make unload event fire in Firefox 4

I have run ajax-calls on the unload event for about a year.
It has generally worked in FF and IE but not to 100%, I cannot say when it has failed.
I register the event by writing in the bodytag:
onunload="...."
I got error messages in FF4 since the unload event also wanted to write in a div-tag of the page that just had unloaded. Fixed this by making the ajax-routine write nothing if the id of the target div is 'dummy'
I am no expert on AJAX, but the following code has worked:
http://yorabbit.info/e-dog.info/tmp/ajax_ex.php (the link is a text-page)
(You call ajaxfunction2 with the following arguments: filename, queryString for PHP, string to show in target div during update, name of target div)
I don't get any error messages in the FF error console and IE9 works. Is there any way I can make it work in FF too?? I have just started trying FF4, but my impression is that it works less well than in FF3.
Thanks.
(I am on a trip and ay not have the possibility to reply immediately, but I really appreciate suggestions and will reply in due course)
EDIT:
I had bettter add this:
The AJAX-call I make on unload does only send some data (how long time the user stayed on the page) to the PHP-MySQL server
I don't know what is happening here, but Firefox 4 has made notable changes to how unloading works: For example, if you do an alert() during a link click event, it will no longer freeze the page, but load the new location anyway. Maybe this is something similar.
However, you are never guaranteed for the Ajax call to finish if it is not synchronous in any browser anyway - the request may or may not come back with a response until the page has been closed. Whether this works will be down to chance, and the user's network speed.
Try using a synchronous request first, as outlined here: How does jQuery's synchronous AJAX request work?
this will usually guarantee that the request comes back. However, use it very sparingly - blocking behaviour at page unload can be very annoying for the user, and even freeze the browser.
I suggest to use jQuery instead of keeping track of browser changes yourself.
Solution:
Find working sample here: http://jsfiddle.net/ezmilhouse/4PMcc/1/
Assuming that your internal links are set relatively, and your external links therefore set starting with 'http':
Leave ...
Stay ...
You could hijack 'a' tags via jQuery events and ask the user to confirm the leaving (in case of external links). In 'ok' case you kick off your 'onleave' ajax call (async=true) and redirect user to external link:
$('a').live('click', function(event){
// cache link
var link = $(this).attr('href');
// check if external link (assuming that internal links are relative)
if (link.substr(0,4) === "http") {
// prevent default a tag event
event.preventDefault();
// popup confirm message
var reply = confirm('Do you really want to leave?');
if (reply) {
var url = 'http:mydomain.com/ajax.php';
var data = {'foo': 'bar', 'fee':'bo'};
// kick off your 'onleave' ajax call
// forced to be synchronous
$.ajax({
type: "POST",
async: false,
url: url,
data: data,
success: function( data ) {
// ok case: leave page, cached link
window.location.href = link;
}
});
}
return false;
}
});

Caching ajax result on client side in asp.net mvc2

I want to do something like
This is screenshot of google transliterator that can be found here. In this application user writes in Roman script and when he/she presses space an ajax request goes to server bringing back list of words. Roman word is then replaced by word top in the result list (Urdu result list in my case). Now when I continue typing and after sometime i come back and see that a word is not like I intended to write.
I click on that word and a context menu would open like shown in the figure, but the important thing is that this time no ajax request goes to the server rather Google picks the result somewhere stored in client area (browser). My question is how can I cache ajax result on client side and second thing is how I can associate each result with each word in text area or rich text box using a context menu or similar interface.
I want to accomplish similar functionality in asp.net mvc2.
Just store the result of your ajax call in a javascript variable - you can access it later on:
var dictionary = new Object();
var input = 'hello';
$.ajax({
url: url,
dataType: 'json',
data: data, // <-- you send your input to server here
success: function(response) {
dictionary[input] = response;
}
});

Resources