How can I cancel a file upload using the jQuery forms plugin - jquery-forms-plugin

I'm using the jQuery Forms plugin to do an asynchronous file upload. Currently, the only way for the user to abort that upload is to press the "Stop" button on their browser, which may cause other javascript and ajax requests to stop as well. I'd like to provide a cancel button, but I haven't found any way to cancel an upload as it is happening using the API.
Is there a built-in way, or at least a robust hack I can use, to cancel the upload as it occurs?

The ajaxForm method takes all the same options that jQuery.ajax takes, so it is possible to capture the dummy xhr that it produces in a beforeSend handler. The xhr has an abort method that aborts the file upload:
f.ajaxForm({
beforeSend: function(xhr) {
cancelBtn.click(xhr.abort);
}});

Since Dec 2012 it is possible to access xhr directly:
var form = $('#myForm').ajaxSubmit({ ... });
var xhr = form.data('jqxhr');
....
$('#cancel').on('click', function(){
xhr.abort();
});
I use it to cancel ajax file upload.
link - https://github.com/malsup/form/issues/221

Related

Is there a way to simulate a link/button click in mink?

I'm using a headless browser (phantomjs) in conjunction with Mink to do some functional testing on my Website.
Now in this setting, files can not be downloaded regularly e.g: by clicking a link. So I have to extract the url from the link or the button, and download the file manually.
As I just stated sometimes there is no link () for the download, but a button in a Form (e.g: Inputting data for a report in the form, and receiving the report file on submission).
So what I need to do is simulate clicking the link or button and extract the Data for the Request that would have been sent, and use that data to download the file manually.
Is there a way to do this?
Note: I'm using guzzle to actually download the file.
Mmmm... I don't know if you solved this and only as an alternative to typical mink methods. As Phantomjs is a javascript based browser engine, did you tried with javascript?
You could try something like this:
public function getElementHref($element)
{
/* #var FeatureContext $this */
$function = "(function(){
//Javascript method to get the href.
})()";
try {
return $this->featureContext->getSession()->evaluateScript($function);
} catch (Exception $e) {
throw new Exception('Element not found');
}
}
You can find a method to do this in javascript here: How to get anchor text/href on click using jQuery?
Then use the URL returned with file_get_contents (depending on the file type) and that's it.

Is there any way to cancel an in-progress upload in dojo?

I have a file uploader that handles very large files. Lots of times the users will cancel an upload. There does not appear to be any way to make the browser cancel the XHR POST that is handling it. Consequently, progress and complete events fire much later and the upload actually completes. Presumably there must be an XHR object embedded in the uploader somewhere that I could call abort on, but I see nothing in the API docs, or in a console dump of the uploader object.
If your goal is to support only the HTML5 uploader (and not the Iframe or the Flash version), then you can do something like that:
Create a new uploader widget with the following (code not tested, might need some adjustment):
define(['dojo/_base/declare', 'dojox/form/Uploader'], function(declare, Uploader) {
return declare([Uploader], {
xhrRequest: null,
createXhr: function() {
this.xhrRequest = this.inherited(arguments);
return this.xhrRequest;
},
cancel: function() {
if (this.xhrRequest && this.xhrRequest.abort) {
this.xhrRequest.abort();
}
}
});
});
Use your new widget instead of dojox.form.Uploader
Call the cancel method when you want to cancel the upload.
But remember: this will work only with the HTML5 uploader.

reCAPTCHA not showing after page refresh

Why is google reCaptcha2 (gReCaptcha) not showing after a page refresh, but showing if page is reopened by the link?
See this video for explanation: http://take.ms/I2a9Z
Page url: https://orlov.io/signup
Page first open: captcha exists.
Navigate by link: captcha exists.
Open new browser tab: captcha exists.
Refreshing page by refresh icon, ctrl+R, ctrl+F5: captcha NOT exists.
I added body unload event to prevent browser cache, it did not help.
Browsers for testing:
Firefix 39.0
Chome: 44.0.2403.125 m
Opera: 30.0
In all browsers I get the same result. So does this mean there's an error on my side?
I think it has to do with the browser and the speed of your network. You are calling ReCaptcha with a callback, but you call it before you define the callback. Depending on your network speed or browser quirks, it might execute before the rest of the script has loaded.
Line 330:
<script src="//www.google.com/recaptcha/api.js?onload=renderReCaptchaCallback&render=explicit&hl=en-US" async defer></script>
Line 351:
<script type="text/javascript">if (typeof (renderReCaptchaCallback) === "undefined") {
var reCaptchaWidgets = {};
var renderReCaptchaCallback = function() {
jQuery.each(reCaptchaWidgets, function(widgetId, widgetOptions) {
grecaptcha.render(document.getElementById(widgetId), widgetOptions);
});
};
}</script>
So I would move the definition of renderReCaptchaCallback to the top of the page so it is defined well before trying to load it.

MVC 4: How to create visual Indicator while FileResult Action generates PDF to be sent back to browser?

I have FileResult Controller Action that can take a couple minutes to run under some circumstances. I would like to provide our users a visual indication that the Action is running, such as a message, a spinner, or a progress bar. The trouble is, I'm having a tough time figuring out how to "detect" on the front end that the Action has completed.
I have been toying with Ajax calls to the FileResult Action, but that doesn't work because Ajax can't return a file to the browser. I also looked at Asynchronous Actions and Tasks, but it looks like FileResult does not support the "await" keyword, which I think is necessary.
At this point, I don't know what to try next, and am very open to thoughts/ideas.
Edit:
I got this working as bobek suggested. Basically, I saved the PDF file to disk, and returned the file path as an ActionResult Content(fullFilePath). Then, on my page, I used something like this to display a little spinner gif while the Action executed, and then a link to the file after it completed.
var img = $("img#reportLoadingIcon");
var link = $('a#exportedFileLink');
link.hide();
img.show();
$.ajax({
url: url,
success: function (result) {
link.attr({target: '_blank', href: result});
link.show();
img.hide();
}
});
You could make it a regular POST action called via AJAX, and instead of returning a File you can return path to file and redirect the user to that path.

How to use jQuery's .on with Rails ajax link?

I'm having a bunch of problems getting jQuery's .on to work with my Rails ajax link.
Specifically, I've got this link:
<div id="item_7_tools" class="item_tools">
<a rel="nofollow" id="book_item_7" data-remote="true" data-method="post" class="book_link" href="bookings">Book this item</a>
</div>
I've trimmed some of the text in the HTML, but suffice to say that that, and my controller response work.
I click "Book this item", it goes off to the controller, the controller does its magic, and sends back my partial that replaces the contents of that div.
So I'm now trying to replace the contents with an ajax spinner while the loading is working, and that's where its going pear-shape.
I'm trying this initial bunch of jQuery code just to make sure I've got my javascript working:
$('div.item_tools')
.on('click', 'a', function() {
console.log("clicky click")
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
})
.on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
My understanding of that, is that when I then click any link (a) that lives within an element with the item_tools class, it will bubble up to this function, and then log the message into the console. Similarly, a link that has triggered an ajax request will get the same treatment...
(And assuming I can get that to work, then I'll go to work doing the ajax loader spinner).
The behaviour I'm seeing instead, is that when I click the link, there are no messages appearing in my console (trying this on both firefox and chrome), and my ajax link goes off and does its stuff correctly. Just completely ignoring the javascript...
Is this because my clicking the ajax link somehow has blocked the click event from bubbling up? I know that there's a way to do that, but I don't think I've done it anywhere knowingly. Unless OOTB rails/ujs does that?
So my questions:
Is there a way to tell what has had a binding attached to it?
What am I doing wrong with my javascript?
Thanks!
I use this all the time... and it seems to work fine.
Have you tried adding one that's .on('ajax:success')?
Besides that try putting the . for each line on the previous line...? It's possible that it gets to $('div.item_tools') and then auto-inserts a semi-colon as per javascript's standard... Although if that were the case I'd expect it to give you a JS error about the . on the next line. In any case try changing it to:
$('div.item_tools').
on('click', 'a', function() {
console.log("clicky click")
}).
on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
}).
on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
If worse comes to worse try just doing:
$("a").on("ajax:success", function(){
console.log('ajax:success done');
})
And see if it works without the event delegation...
Then change it to this:
$(document).on("ajax:success", "a", function(){
console.log("ajax:success with delegation to document");
})
And see if delegation works all the way up to document instead of just your item_tools
Are you sure that you've named everything right? it's div.item_tools a in your markup?
Turns out that the javascript was being triggered before the DOM had loaded, which meant that stuff weren't being bound...
$(function () {
$('div.item_tools')
.on('click', 'a', function itemToolsAjaxy() {
console.log("clicky click");
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
$(this).closest('div').html('<img src=/assets/ajax-loader.gif>');
})
});
Added the $(function()) right at the beginning and it delayed the binding until after the DOM had loaded, and then it started working.
Figured this out by using the Chrome developer tools to stick a break on the div.item_tools selector and watched as the browser hit that even before the DOM had been loaded. /facepalm
(I removed the .on('ajax:complete') callback, because it turns out that there's a known limitation where the original trigger element no longer exists because it had been replaced, so there's nothing to perform the callback on. Not relevant to my original problem, but I thought I'd mention it.)
As far as i'm aware, you can either do ajax stuff 2 ways:
By using :remote => true
By using jQuery's $.ajax (or $.post).
With number 2, make sure to change your href='#'
My suggeston is to remove the :remote => true and manually make a jQuery ajax call. That way you can use beforeSend, complete, etc.
If i'm way off track here, someone please help clarify things for me as well.