So I have the weirdest problem, in my company's CMS we have a newsletter system that does an AJAX call to send an e-mail. Now this works perfectly in all modern browsers on all operating systems, however it does not for one client.
This client is using Windows 7 and IE9, I have Windows 7 myself and tried IE9 (even with all compatibility modes) but it would always work.
I don't know why it doesn't work for them, however I was able to "fix" it by placing an alert before and inside the AJAX call.
I am thinking it must be something with their hardware or connection, and was hoping somebody might have an explanation. Here is the AJAX call (with the alerts) so you can see there is nothing wrong (right?):
$('#send_single').unbind().click(function(event) {
event.preventDefault();
processing();
alert('one');
$.post(
'newsletter/ajax.php',
{
action: 'send_single',
email: $('#single_email').val(),
template: $('#select_template').val(),
id: $('#select_newsletter').val()
},
function(data) {
alert('two');
finished_processing();
cmsalert(data);
}
);
});
processing() fades in a processing box, which finished_processing() then removes. Without the alert boxes the finished_processing() never happens, with the alertboxes it runs as expected.
processing() and finished_processing()
function processing(){
$('#full_overlay').fadeIn();
$('#processing').fadeIn();
}
function finished_processing(){
$('#full_overlay').fadeOut();
$('#processing').fadeOut();
}
#full_overlay is a fullscreen fixed div with a white overlay. #processing is a centered div containing a loading gif and a "Please wait..." string.
finished_processing() doesn't happen, so I don't think cmsalert() is in any way related. (cmsalert slides in a div at the bottom of the page containing a - usually success - message)
Try something like the example show in the jquery docs, changing your finished_processing function like:
function finished_processing(){
$('#full_overlay').promise().done(function() { this.fadeOut(); });
$('#processing').promise().done(function() { this.fadeOut(); });
}
You may also face problems if the client clicks several consecutive times, keep that in mind. I believe the return of $.post() can also be used in the same lines ($.post().promise() or $.post().done) in case you could store in a variable and use that. You may also like to have a look at Deferred Object.
Related
Hey I'm making a custom backend for Wordpress, it's a bit 'ghetto' but it turned out to be bigger than expected so I'm running with it. Works perfectly fine stylistically and functionally but for some reason if I submit a new post with it, I get "Are you sure you want to navigate away from this page?" or whichever browser equivalent.
I've tried a shitton of variations of onbeforeunload = null, returning blank functions, etc, none of the solutions have worked on any browser, so I assume it's something to do with Wordpress backend constantly updating...?, I read that it might be a factor that you can't bind onbeforeunload like a normal event as well, so a combination of these two makes me wonder, how can I permanently silence "are you sure" notices on a page, no questions asked?
It seems everywhere on the web is a variation of this question and/or setting the onbeforeunload null worked for them, it does not in any sense for me, even in inline JS onthe form. I have no idea why it's even triggering, I assume I moved something when reconstructing the WP submit form that causes it to ungroup data... or something, but I just need to silence all dialog from this page that is "save changes", that's all, seems like it's easy enough with a bind/event handler but they haven't worked and I don't quite get how the event works.
I've tried this and some other binds thus far, as well as putting return onbeforeunload null function inline the form
window.onbeforeunload = function() {
return null;
}
window.onbeforeunload = null;
jQuery('a, input').click(function(){
window.onbeforeunload = null;
});
If the events were registered using jquery with $(window).on('beforeunload' you can remove them using $(window).off('beforeunload'
This example demonstrates the click event, but it works the same with the beforeunload event:
$(function() {
$(window).on('click', function() {
alert(1);
});
$(window).on('click', function() {
alert(2);
});
$(window).off('click')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I use the following script to get the content of the remaining.php.
The drawback is that sometimes it doesn't work or it is kinda slow to display the text. Is there any other way of doing this ?
Thank you
$(document).ready(function(){
$("#SubmitButton").click(function (){
$('#remaining').load('remaining.php');
});
});
You could directly include the contents of remaining.php into the initial markup but make it hidden by applying display:none; style to the #remaining element. Then when the button is clicked simply show it:
$(function() {
$('#SubmitButton').click(function () {
$('#remaining').show();
});
});
Of course if you need to pass some parameters to the script which will depend on some javascript variables that are known only at the moment the button is clicked you will need to use AJAX as you are currently doing.
If "sometimes it doesn't work or it is kinda slow", the problem is probably the server you are using, not your javascript code.
The javascript code you're showing us here doesn't really do anything that could be slow, it only binds an event on a submit button. However, what could be slow is waiting for the answer from your web server when sending a request for remaining.php
From there, there is a thousand of reasons why your web server could be slow. Maybe you could post the content of your remaining.php file so we can see what is going on in there.
This isn't really a fault of jQuery, but the speed of return from your server. Perhaps there's a better way to handle it instead of fetching a full page?
For example, if your content request was only retrieving a message, you could return JSON from your server and have jQuery handle the data:
$(document).ready(function(){
$("#SubmitButton").click(function (){
$.post('remaining.php',
null,
function(data) {
// do stuff with your JSON result
});
});
});
When you're using .load(), you're sending a request to the server to get your content, which is why it can seem slow. I'm not sure why it sometimes won't work , but I would venture to guess that you may be clicking $("#SubmitButton") before $(document).ready fires.
Depending on your implementation, you may be able to refactor your application so that the text you want to display is pre-loaded on the page.
I have a fully ajaxed website, which uses jQuery's $.get calls to fetch the central content of the website upon header clicks.
One of the "screens" (views, actually, using Zend) has a hidden div which is "dialoged" when a user clicks a certain button. This is what happens to me:
I get to the desired screen, and click the open dialog button.
Dialog opens fine. Closing and reopening works as expected.
I go to another screen (mind you, this is ajax, which simply replaces the main content with new content - the hidden div is inside this content, however, and gets replaced along with the main content)
I come back to the previous screen (still ajaxing), and click the open dialog button again. Now all of a sudden, there are two of those hidden divs, both with the identical ID (I can see that if I do a console.log($("div#hiddenDiv").length); ) and they are both spawned in dialog form - I have them on top of each other.
The dialogs get duplicated for as many times as I redo this. If I go to another screen, come back, and open dialog again - I get 3, etc.
I took a lot of precautions - I empty the memory at every ajax click, setting all variables I have nothing to do with anymore to null. I also take care to replace the entire content, the hidden divs as well, on every new ajax call, i.e. screen-transition. I checked and made sure that the function which summons the dialog isn't called more than once - it simply dupes the dialog upon returning to the screen which contains it by default, and I have no idea why. Mind you - no other element is duped. Only this hidden soon-to-be-dialog div.
Also worth noting is the fact that the duping process never begins until I open the dialog for the first time. From that moment on, every ajax [departure/return/dialog-opening]-scheme dupes the invisible div.
Does anyone have any idea why this is happening?
Edit: Code example:
// This causes the screen change when it detects a hash change
// ... stuff ...
if(window.location.hash){
ajaxData(newhash);
}
// ... stuff ...
// This causes the actual change of on-screen content (i.e. this is the ajax call)
function ajaxData(value) {
// ... stuff ...
$.ajax({
url: "/siteexample/"+value,
type: "GET",
mode: "abort",
dataType: type,
success: function(data){
$("#main_content").html(data); // the hidden div is always inside this "data", so it always gets removed when a new screen loads
loaderdisplay('hide');
// Clean Memory
data = null;
},
data: ({ajax : 'Y'})
});
// ... stuff ....
// And finally, this is the part that summons the dialog
function summonDialog() {
console.log("here"); // this shows up only once, so I know this function is not called multiple times.
var dialogBox = $("div#new_window"); // this is the infamous div
$(dialogBox).dialog({
modal: true,
title: "Some title",
resizable: false,
zIndex: 22000,
width: 800,
buttons: {
"Save": function(){
// some function, ends with:
$(dialogBox).dialog("close"); // destroy doesn't change anything
dialogBox = null;
},
Cancel: function(){
$(this).dialog("close"); // destroy doesn't change anything
dialogBox = null;
}
}
});
}
So the sequence of events is:
1. ajaxData to the location where the div is.
2. ajaxData away from it.
3. ajaxData back, and open dialog, everything fine.
4. ajaxData away from it.
5. ajaxData back and open dialog, duped.
Rinse and repeat, from now on they're getting duped.
Edit2:
I was able to temporarily hack this into a fix with this in the summonDialog function:
var dialogBox = $("div#new_window");
var usableDialog = dialogBox[0];
$(dialogBox).remove();
$(usableDialog).dialog({
// ... dialog code as usual ...
But I don't like the solution much. Marc's explanation makes sense, but since I have many different hidden divs with the potential to become dialogs scattered across many different views, removing each one in such a way would be tedious, since they tend to have different context-appropriate IDs and removing by "ui-dialog-content" class (which all divs get once they're dialog-opened) could produce some issues in other parts of the site, since it's a too general scope.
I believe the div that is the dialog will be attached and hidden on the body. Thus, when you replace the #main_content html, you're not really removing it. I would recommend removing the div and re-enabling the .dialog plugin on each html(data) reload.
Something like this:
success: function(data){
$("#new_window").remove();
$("#main_content").html(data);
loaderdisplay('hide');
summonDialog();
}
And easy way to test this is to simply console.log($("#new_window").length); when you get dupes.
I had exactly the same problem, The dialog was duplicated even after
$('.content').html('');
So I added this:
$("#divEditAdvice").remove();
That was the solution as #Marc mention above.
I'm working on an ASP.NET Web Project with some AJAX magic. As my GridView's data needs up to 15 seconds to be gathered, I send the page to the client and fire an asynchronous update of an UpdatePanel via jQuery/JScript (see below).
This works well, so far. Now I'd like to skip this step when the user navigates to the next page (e.g. record detail view) and comes back via the "Back" button. Is there a way to get his, and what's the most elegant one?
This one does not work (hasDonePostBack's value isn't kept by the browser):
var hasDonePostBack = false;
function fRefreshAsyncOnce(id, param) {
$(document).ready(function() {
if (!hasDonePostBack) {
__doPostBack(id, param);
hasDonePostBack = true;
}
});
}
Any help would be great!
The reason why this is important: Regetting the data takes another 15 seconds. Moreover, the grid is working with controls and more client script (e.g. checkboxes that can be checked, CSS classes that are toggled, etc.), and all this should be the same after returning.
Cheers,
Matthias
You may want to look at the history point feature; you may be able to take advantage of that for this feature: http://msdn.microsoft.com/en-us/library/cc488548.aspx
However, that is the nature of the beast when triggering client-side operations... the other option is allowing the user to cancel the postback (or try to interpret a way to cancel it yourself) using this technique: http://msdn.microsoft.com/en-us/library/bb398789.aspx
I have gone insane trying to figure out how to make this work. Code looks roughly like:
function onDropDownChanged() {
$("#updatePanel").load(
"myUrl",
{ id: $("#myDropDown option:selected").val() },
onPanelLoaded
);
}
function onPanelLoaded() {
$("#theTextInput").focus();
}
$(document).ready(function() {
$("#myDropDown").change(onDropDownChanged);
}
The first time the change handler is fired, it does the ajax update, and the text box is focused.
However, on subsequent changes, it continues to do the ajax update, but the text box is never focused again.
I found that if in onDropDownChanged, I added $("#updatePanel").empty() before the ajax call, the text box would always get focused. The problem with that is the entire form disappears for a second, causing an ugly flash. Given ajax is supposed to make things like this nice, it's not a workaround I want to use.
It seems like it should work, but I wonder if the DOM isn't updated by the time the callback is invoked. You might want to see if introducing a delay helps.
function onPanelLoaded() {
setTimeout( function() { $("#theTextInput").focus(); }, 500 );
}
Including the HTML on the page and what is returned via load() would be helpful if this doesn't work.
I had a similar problem with IE6 and IE7, but setTimeout() was not a reliable solution. Sometimes it worked, sometimes it did not. It didn't work on some machines at all, and the 500ms value was completely arbitrary anyway. The focus() function worked exactly as expected without any timeout in both Firefox and Chrome, of course.
My solution was to call focus() twice for IE:
function onPanelLoaded() {
var panel = $('#theTextInput');
panel.focus();
panel.focus();
}
Now THAT did what I intended in the first place.