ASP.NET MVC - time ajax request - asp.net-mvc

I'm using a jQuery modal dialog to display a 'Please Wait' type message to a user when a ajax call is made back to the server.
I'm doing this by making the dialog visible using the jQuery ajaxSend method. And I close the dialog using the jQuery ajaxComplete method.
All fairly routine stuff I'm sure.
However if the call takes a very short about of time (say 10 milliseconds) then I want wait until a second has passed since making the dialog visible before I then close the dialog. The reason is to provide user feedback ... and to stop the horrible flicker of the dialog quickly opening and then closing.
How can I achieve this using jQuery and / or ajax?
Many thanks for any pointers.

Would a better paradigm be to actually wait for a period of time before showing the dialog? If you have a responsive app then it would make sense to only show the modal if the response does not come back within say 100ms. This would avoid delaying the UI just to avoid flicker which is what you are proposing.
Note I am using beforesend and success here to dummy up the code
var timerid;
beforeSend: function(){
//open the dialog in 100 milliseconds
timerid = window.setTimeout( function(){
$('#dialog').dialog('close');
}, 100)
},
success: function(){
//cancel the showing of the dialog if not already called
window.clearTimeout( timerid );
//close the dialog regardless
$('#dialog').dialog('close');
}
If you dont like this idea then simplay put the dialog close function inside a setTimeout within the ajax complete callback e.g
complete : function(){
//close the dialog in 1 second
window.setTimeout( function(){
$('#dialog').dialog('close');
}, 1000)
}

I've pulled together a solution for this myself - based on the great response from 'redsquare' and some further reading.
I have used the code from redsqure to open the modal dialog only after a given duration has passed - thus hopefully not having to open the modal at all.
For when the modal has opened I've added code to ensure it remains open for a minimum of 800 milliseconds ... just to avoid the possibility of it quickly flashing up on the screen. To achieve this I start a javascript timer in the 'ajaxSend' method and then I use the 'ajaxComplete' method to determine whether the modal is open. If so I use the timer to calculate how long it has been open for and make up the difference to 800 milliseconds. I adapted a script I found on line for my timer. Script below.
var timer_ms = 0;
var timer_state = 0;
/// <summary>
/// Responsible for starting / stopping the timer. Also calculates time.
/// </summary>
function timerStartStop() {
if (timer_state == 0) {
timer_ms = 0;
timer_state = 1;
then = new Date();
then.setTime(then.getTime() - timer_ms);
}
else {
timer_state = 0;
now = new Date();
timer_ms = now.getTime() - then.getTime();
}
}
/// <summary>
/// Resets the timer.
/// </summary>
function timerReset() {
timer_state = 0;
timer_ms = 0;
}
Thanks.
Thanks.

Related

Zendesk web widget status not correctly updating and button not hiding

I'm loading the Zendesk web widget into a page, and this is the event handler for when it's loaded in
scriptElement.onload = function () {
zE(function () {
$zopim(function () {
$zopim.livechat.button.setHideWhenOffline(true);
$zopim.livechat.setOnStatus(function (status) {
console.log('status',status);
status === 'online' ? $zopim.livechat.button.show() : $zopim.livechat.button.hide();
});
$zopim.livechat.setStatus('offline');
});
});
};
It has the setOnStatus event handler which should trigger anytime the status changes. It seems to be triggered once when the page initially loads in. You'd expect it to be triggered as well everytime I call the setStatus method, but that's not the case. Where I log the status, it's always just 'online', and it only happens once.
What I'm trying to do is force the button to disappear when the status is offline. Yet setting the status to 'offline' doesn't hide the button, just displays the offline version (i.e. a button which lets me send an offline message, rather than a live chat).
I thought the setHideWhenOffline method might have helped, but that doesn't seem to make any difference in this case.
Any ideas?
Actually I found the solution I needed here, this prevents the offline button appearing.
window.zESettings = {
webWidget: {
contactForm: {
suppress: true
}
}
};
https://developer.zendesk.com/embeddables/docs/widget/settings#suppress

Stop the back history, juste close panel [duplicate]

I have a jQuery mobile panel which slides in from the side, it works great.
But lets say you have a login page, that redirects to a main page with a panel. Now if the user opens the panel, and then clicks the back button, he expects the panel to close. But instead the browser navigates back to the login page.
I´ve tried adding something to the url:
window.location.hash = "panelOpen";
But that just messes up the jQuery mobile history state pattern. I´ve also tried to listen to the navigate event, and prevent it if a panel is open:
$(window).on('navigate', function (e, hans) {
var panels = $('[data-role="panel"].ui-panel-open');
if (panels&&panels.length>0) {
e.preventDefault();
e.stopPropagation();
$('#' + panels[0].id).panel('close');
return false;
}
});
This kind of works, except that the url is changed, and I cannot grab the event that changes the url. Furthermore, it also messes up the jQuery mobile history pattern.
So how does people achieve this expected 'app-like' behaviour with a jQuery mobile panel; open panel > history back > close panel. And thats it.
Thanks alot!
Updated
Instead of retrieving current URL from jQuery Mobile's history, It is safer to retrieve it from hashchange event event.originalEvent.newURL and then pass it to popstate event to be replaceState() with that URL.
Instead of listening to navigate, listen to popstate which fires before. The trick here is manipulate both browser's history and jQuery Mobile's history by replaceState() and reload same page without transition.
var newUrl;
$(window).on("hashchange", function (e) {
/* retrieve URL */
newUrl = e.originalEvent.newURL;
}).on("popstate", function (e) {
var direction = e.historyState.direction == "back" ? true : false,
activePanel = $(".ui-panel-open").length > 0 ? true : false,
url = newUrl,
title = document.title;
if (direction && activePanel) {
$(".ui-panel-open").panel("close");
$(".ui-header .ui-btn-active").removeClass("ui-btn-active");
/* reload same page to maintain jQM's history */
$.mobile.pageContainer.pagecontainer("change", url, {
allowSamePageTransition: true
});
/* replace state to maintain browsers history */
window.history.replaceState({}, title, url);
/* prevent navigating into history */
return false;
}
});
This part is meant to maintain same transition used previously as transition is set to none when reloading same page.
$(document).on("pagebeforechange", function (e, data) {
if (data.options && data.options.allowSamePageTransition) {
data.options.transition = "none";
} else {
data.options.transition = $.mobile.defaultPageTransition;
}
});
Demo - Code
I am a little bit late on the party, but i had recently the same requirements and i would like to share how i did it. So, i extended the requirement in the original question to Panels, Popups and Pages:
...an expected 'app-like' behaviour, history back > close
whaterver is open. And thats it.
In .on("panelopen"), .on("popupafteropen") and .on("pagecontainershow") i simply add another entry to the window history, by using the HTML5 API (https://developer.mozilla.org/en-US/docs/Web/API/History_API) (I believe there is no need to use the JQM navigate browser quirks for that):
window.history.pushState({}, window.document.title, window.location.href);
After that, i'm using more or less Omar's function to intercept the popstate event:
$(window).on("popstate", function (e) {
var pageId = $(":mobile-pagecontainer").pagecontainer("getActivePage").prop("id");
var pageOpen = (pageId != "page-home");
var panelOpen = $(".ui-panel-open").length > 0;
var popupOpen = $(".ui-popup-active").length > 0;
if(pageOpen) {
$.mobile.pageContainer.pagecontainer("change", "#page-home", {reverse: true});
return false;
}
if(panelOpen) {
$(".ui-panel-open").panel("close");
return false;
}
if(popupOpen) {
$(".ui-popup-active .ui-popup").popup("close")
return false;
}
});
As you see, the is just only one level to the home-page, but this can be easily extended by using JQM history implementation to get the previous page:
var activeId = $.mobile.navigate.history.activeIndex;
var jqmHistory = $.mobile.navigate.history.stack; // array of pages
and use pagecontainer to change to the active entry - 1.
As last note, this works well also by completely disabling the built-in JQM Ajax navigation system:
/* Completely disable navigation for mobile app */
$.mobile.ajaxEnabled = false;
$.mobile.loadingMessage = false;
$.mobile.pushStateEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.changePage.defaults.changeHash = false;
$.mobile.popup.prototype.options.history = false;
(Tested in Browser, on real Android and iOS devices)

Back button handler in jQuery Mobile (Android) PhoneGap

Is there any way to handle back button (device backbutton) as default functionality to move back page? I need to implement the same functionality on back button goes to previous page. If there is no previous page (first page) it exit the application. Is this possible in PhoneGap?
I also need to pop page before going to push another page is this posible in jQuery?
Checking window.location.length would be the easiest way to determine if you're on the first page, but this isn't available in Phonegap.
But since you're using JQM, you can either use the navigate event as Omar suggests or could manually count the number of pages shown and the number of pages gone back (same thing) and use this to determine if the first page is being shown and whether to exit the app. Something like this would work:
var pageHistoryCount = 0;
var goingBack = false;
$(document).bind("pageshow", function(e, data) {
if (goingBack) {
goingBack = false;
} else {
pageHistoryCount++;
console.log("Showing page #"+pageHistoryCount);
}
});
function exitApp() {
console.log("Exiting app");
navigator.app.exitApp();
}
function onPressBack(e) {
e.preventDefault();
if(pageHistoryCount > 0) pageHistoryCount--;
if (pageHistoryCount == 0) {
navigator.notification.confirm("Are you sure you want to quit?", function(result){
if(result == 2){
exitApp();
}else{
pageHistoryCount++;
}
}, 'Quit My App', 'Cancel,Ok');
} else {
goingBack = true;
console.log("Going back to page #"+pageHistoryCount);
window.history.back();
}
}
function deviceready() {
$(document).bind('backbutton', onPressBack);
}
$(document).bind('deviceready', deviceready);
As for the second part of your question:
Secondly i need to pop page before going to push another page is this
posible in jquery ?
It's not clear what you're asking here. Do you mean you want to show some kind of popup content like a dialog between every page change? Please clarify then I can help you :-)

Knockout View Instantiating JQuery Datepicker Control onSelect Not Updating DOM Until JS Finishes Executing

I have a page that is created completely using Knockout. In one of the templates, clicking on a link will display a JQuery Datepicker control to select a date. Upon selecting the date, a function executes using the selected date and the Datepicker closes. That much works just fine.
It can take several seconds from when someone selects a date until the Datepicker closes. This is due to a function that is called (LoadAppointmentTimeSlots) which needs to run synchronously and can take a while to do what it does. To address this, I would like a DIV to appear that provides feedback to the user that the system is working ("#loading").
THE PROBLEM is that the DIV does not appear until after the LoadAppointmentTimeSlots function executes (by which time the DIV gets hidden again). I have experimented with setTimeout in several ways, but nothing has worked.
Below is the "offending" code:
var SchedulingViewModel = function () {
var self = this;
...
self.Date_OnClick = function () {
var selectedDate;
$("#calendarPopup").append('<div id="datepicker" />');
$("#datepicker").datepicker({
dateformat: 'mm-dd-yy',
changeMonth: true,
changeYear: true,
setDate: new Date(),
minDate: 0,
maxDate: self.SelectedRFVInterval() - 1,
onSelect: function (datetext, inst) {
selectedDate = datetext;
$("#loading").show();
self.LoadAppointmentTimeSlots(datetext); // function within view model that uses $AJAX in sync mode to return time slot data
$("#loading").hide();
$('#calendarPopup').dialog('close');
}
});
};
...
}
The difficulty you are running into is because show() is executed asynchronously, and since javascript is executed in a single thread, that means they have to wait until all synchronous code (such as LoadAppointmentTimeSlots) is done.
To get your desired behaviour, put everything after the show() call into the callback for the show command. That way LoadAppointmentTimeSlots won't execute until the show() call is done. Here is how:
// ... other code
$("#loading").show(function() {
self.LoadAppointmentTimeSlots(datetext);
$("#loading").hide();
$('#calendarPopup').dialog('close');
});
However, it might be better to change your ajax call in LoadAppointmentTimeSlots to be asynchronous and move the hide() and dialog('close') calls to the callback of the ajax call. This allows javascript to keep doing other things while you are waiting for LoadAppointmentTimeSlots to finish. That might look more like this:
// ... other code
$("#loading").show()
self.LoadAppointmentTimeSlots(datetext, function() {
$("#loading").hide();
$('#calendarPopup').dialog('close');
});
// ... more code
function LoadAppointmentTimeSlots(datetext, alwaysCallback) {
// Prepare request details
$.ajax( "/myendpoint?param=foo" )
.done(function(data) { alert("success"); }) // do something with data
.fail(function() { alert("error"); })
.always(alwaysCallback); // called on both success and failure of ajax call
}

Progress bar on calling controller in Asp.Net MVC 2

I want to show progress bar when user submit the form because that process will take time may be around 8 to 10 seconds, so i want to show the progress bar so user must have an idea of how much time it will take. This process will be executed on simple call of a controller action like normal postback no ajax involve. So how can i achieve this task i am using asp.net mvc 2
Fraz,
Whilst i notice you say NO AJax INVOLVED, thought I'd chuck this in for info purposes.
As long as you don't care about the 'plase wait' indicator showing exact progress, then there's a simple way to do this with jquery and my answer here is dependent on that.
basically, create a 'Wait' view that contains a simple message along with an animated gif embedded within it. then just fire off your insert (or long running action) via the following basic outline:
$(document).ready(function() {
$('#btnSave').click(function() {
$.ajax({
type: "POST",
url: '<%=Url.Content("~/Booking/Save") %>',
data: { data: prepareData() }, // your data properties to be saved
beforeSend: beforeQuery(),
success: function(data) {
saveDataResponse(data);
},
error: function(xhr) { alert(xhr.statusText); }
});
});
});
// here we show the 'wait' view prior to processing starting
function beforeQuery() {
var url = '<%= Url.Action("Wait", "Booking") %>';
$("#mainDiv").load(url);
}
// when the long running process has completed (or error'd)
// either populate mainDiv with the details view of the booking
// or show the error appropriately
function saveDataResponse(data) {
if (data.length != 0) {
if (data.indexOf("ERROR:") >= 0) {
$("#mainDiv").html(data).css('backgroundColor','#eeaa00');
}
else {
$("#mainDiv").html(data);
}
}
}
obviously, there would be a little more involved for error conditons etc, but this is the basic 'template'.
hope this helps

Resources