In jQuery, is there any way to mask whole page automatically when we execute each Ajax post (to prevent input from user or double submitting...)? I see this plugin: jQuery-blockUI (http://www.malsup.com/jquery/block/) but we still have to mask/unmask manually for each Ajax post.
As I know in ExtJS, we can control this by implementing "beforeAction" function, because this event will be fired right before any action on form, but in jQuery I do not find out anything like that.
Could you please give me a solution for this? Thank you so much.
It wouldn't be too hard to do this yourself.
HTML
<body>
<div id="mask"></div>
<!-- Everything else -->
</body>
CSS
#mask{
position:fixed;
width:100%;
height:100%;
background: /* You can make this slightly transparent black rgba(0,0,0,.3); or transparent */;
top:0;
left:0;
display:none;
}
JAVASCRIPT
var isPageMasked = false,
mask = $('#mask');
var maskPage = function(){
if(isPageMasked){
mask.hide();
} else {
mask.show();
}
isPageMasked = !isPageMasked;
};
Then you would just call maskPage() when you make you want to mask and unmask the page.
You can just use the beforeSend and complete functions
$.ajax({
beforeSend: function() {
//Mask page
},
complete: function(){
//remove Mask
}
}
});
Related
User makes repeated queries against database over the course of the day; each time, the results are cleared from the table and new data are injected into the table:
<tbody data-bind="foreach: MyVM.Results">
and in code before the ajax call:
MyVM.Results.removeAll();
I want to display an animated spinner of some kind while the ajax call is underway (Edit: and then also when ko is still working on creating the table rows after the ajax call returns).
EDIT: What is "the knockout way" of displaying this animation when there's a standard ajax call with fail and success callbacks, and the tbody is foreach-bound to the observableArray Results?
EDIT2: configuring the Ajax call itself in jQuery with beforeSend and complete callbacks does not solve the problem entirely because taking UI action when the ajax call itself is complete does not account for the delay of knockout's for-each binding of the data to the table. is there a knockout event that signals "binding complete"?
EDIT3: The answers are not understanding the problem. My fault for trying to make it simple and leaving out a lot of code. This has nothing to do with Ajax. Consider this very simple scenario, which is exaggerated to make the problem clearer. Let's say you have an array with a million items in it. Ajax call is already completed! Now you want to get the items in that array into a ko observableArray to which your TABLE TBODY is bound with for-each binding. This binding process itself is going to take some seconds to complete We want to hide our animation after the binding has finished and something is displaying on the HTML page. Is there a way to know that the table rows created by knockout have begun to be rendered in the UI?
I developed a custom loading animation for doing this.
<!--Preloader-->
<div id="preloader">
<div class="preloader" data-bind="visible: _isShow">
<div class="loader-content">
<img src="img/ajax-loader.gif" alt="Loading.." style="margin: 0px auto 20px auto;">
<br>
<span class="loader-txt">Loading... Please wait....</span>
</div>
<!--End of loader-content-->
</div>
<!--End of preloader-->
</div>
CSS codes
/*****************Preloader******************/
.preloader {
background: rgba(0, 0, 0, 0.9);
width: 100%;
position: fixed;
z-index: 10000;
top:0;
bottom:0;
left:0;
right:0;
}
.preloader-hidden{
visibility: hidden;
}
.preloader .loader-content {
text-align: center;
top: 50%;
margin-top: -22px;
position: absolute;
left: 50%;
margin-left: -75px;
}
.loader-txt {
font-size: 14px;
color: #fff;
vertical-align: middle;
margin-left: 15px;
}
Javascript Code for preloader viewmodel
function PreloaderViewModel() {
var self = this;
self._isShow = ko.observable(false);
self.ShowPreloader = function() {
self._isShow(true);
};
self.HidePreloader = function() {
self._isShow(false);
};
}
Register the view model as bellow
var preloaderVM;
if ($.isEmptyObject(preloaderVM)) {
preloaderVM = new PreloaderViewModel();
ko.applyBindings(preloaderVM, document.getElementById("preloader"));
preloaderVM.HidePreloader();
}
Use it in ajax call like bellow.
//Show preloader
preloaderVM.ShowPreloader();
$.ajax({
type: "GET",
dataType: "json",
url: yourServiceUrl,
data: searchdata,
success: function (data) {
//do whatever in data return from ajax call
//Hide preloader
preloaderVM.HidePreloader();
},
error: function (error) {
console.log(error.responseText);
preloaderVM.HidePreloader();
}
});
If you want to change the text showing in pre-loader by defining a property on preloaderviewModel.
ko way is to use model to drive the view.
If the standard ko bindings are not enough (for instance, if gif animation is not enough for you), create a customised ko.bindingHandlers.
An idea ko app hides all DOM manipulation inside ko.bindingHandlers.
Here is a template that I use for ajax data loading.
HTML
<!-- ko if: loading -->
<!-- show spinner -->
<!-- /ko -->
<!-- ko ifnot: loading -->
<!-- show result, your data-bind="foreach: Results" -->
<!-- /ko -->
Javascript
//assume you use self to hold 'this' pointer in viewModel constructor
self.loading = ko.observable(false);
// in your data loading action
self.loadRemoteData = function() {
//start loading
self.loading(true);
$.ajax({
// ...
success: function(data) {
// update Results(data);
},
fail: function() { ...},
complete: function() {
//finish loading
self.loading(false);
}
});
};
I found the answer. Instead of looping through the Ajax data and adding an object to the ko observableArray on each iteration, I have to pop or shift() each item off the Ajax data array and push it onto the observableArray in a custom event using trigger(). The eventhandler invokes the custom event again and again while data contains items. Thus, the UI is not blocked but table rows begin to appear immediately.
In my case, the web app is running on an intranet, and the local database can return 10,000 rows on the LAN in the blink of an eye, but it takes a good number of seconds for all 10,000 rows to be created in the HTML Table using knockout for-each binding. With the event approach, the rows start becoming visible to the user instantly.
$(document).on("PushIt", function (event, data, results) {
var item = data.shift();
var Cust = new Customer(
item["firstname"],
item["lastname"],
item["addr1"],
item["city"],
item["state"],
item["zipcode"]
)
results.push(Cust);
if (data.length > 0) {
// timeout avoids recursion-limit problems
setTimeout(function () { $(document).trigger("PushIt", [data, results]); }, 1);
}
});
I'm currently using jQuery Waypoints to highlight nav items as you scroll through sections of the page. All of that works fine; thanks to copying the code from the demo at http://imakewebthings.github.com/jquery-waypoints/.
My demo is: http://www.pandlmedia.com/index.php/index_new
However, I also want to create a waypoint at the #footer div which would trigger an event to change the color of all of the nav links.
$('#footer').bind('waypoint.reached', function(event, direction) {
$('.nav ul a').addClass('white');
});
This doesn't work, as there's nothing telling it to change back once it exits the #footer div. I'm not very experienced in writing jQuery or using this plug-in for that matter. What do I need to add to make this work? Is the fact that there are two levels of waypoints also causing problems?
well, looking closer at the "sticky elements" demo, I was able to modify the example of the disappearing '.top' button to make this work for my own needs described above:
<script type="text/javascript">
$(document).ready(function() {
$('.container .nav ul a').addClass('black');
$.waypoints.settings.scrollThrottle = 30;
$('#footer').waypoint(function(event, direction) {
$('.container .nav ul a').toggleClass('black', direction === "up");
}, {
offset: '50%'
});
});
The key was to add the .black class below the .white class in my css so that it overrides the color parameter properly.
I have several methods in my models, which are called by my controller. On the client, I want to update a progress bar while the model methods are running.
How can I communicate with the controller to get its progress?
True that you need AJAX / long polling to make this work. Here is XMLHttpRequest2. And to me, this has taken the web to next level. Its time for us to use it. I ve used it with jquery. Probably a lot more easy to understand what I ve done. Might need a little tweak to make it work. Here it goes..
$.ajax({
type: 'POST/GET',
url: "link/to/controller/method",
data: {whatever = 'foo'},
beforeSend: function(XMLHttpRequest)
{
//Upload progress
XMLHttpRequest.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
$( ".jquery-uploadbar-selector" ).progressbar({ value: percentComplete }); //jquery progress bar for upload
//incase you wanted an upload bar
}
}, false);
//Download progress
XMLHttpRequest.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
$( ".jquery-downloadbar-selector" ).progressbar({ value: percentComplete });
//jquery progress bar for download or in other words The real answer for question
}
}, false);
},
success: function(data){
//Here goes the end of what you have done.. I would just type..
console.log('Yay!! I guess, I ve answered my first bounty question and hoping to see it work well.');
}
});
Hope it works.. let me know if I am wrong somewhere.
You can't do this using PHP since PHP is server side and when it has completed its work the result is sent to the browser.
You may use Javascript to make AJAX call (google this, it is a way to make call to the server without reloading the page) and each time a method of the model is completed you may add 'loading' to your progress bar using JS. but really in PHP there isn't a way to know how much of an action has been completed
There are ways to do this with file uploads via Apache and NGINX, however that won't apply to your situation.
One way of doing it would be to use AJAX long polling to monitor a special controller or method of your controller to look for updates and update on the frontend when it changes.
have http connection open with client(user) and when you start the job send data(isWaiting=1) to your client or do ajax polling as Asiq said and fetch isWaiting status.
on html client side page , javascript to load progress bar when isWaiting=1
html page having this inside body tag
<div class="overlay" style="display:none;"></div>
and css
.overlay { width:100%; height:100%; z-index:5000; left:0;/IE/ top:0;
text-align:center; position:fixed;
background: url('https://memberschemes.rics.org/MembersPortal/images/ajax_loader-2.gif') no-repeat fixed center center;
background-color: #EFEFEF;
opacity:0.7;
/*
background: #F4F4F4;
background-repeat: no-repeat;
background-position: center;
*/
}
I have been trying every possible combination of cufon.replace - Cufon.refresh and Cufon.reload but i just cant seem to get this working. when original page loads cufon does its job, but when Ajax loads new content the cufon is missing. here is my java hope this makes sense to anyone, Cufon fires first, followed by Ajax,
jQuery.noConflict();
/*
* TYPOGRAPHY
*/
Cufon.set('fontFamily', 'ColaborateLight');
Cufon.replace('h2, #main h3, h4, h5, h6, #slogan, .label', {
hover: true
});
Cufon.set('fontFamily', 'Colaborate-Medium');
Cufon.replace('#main_home h3', {
hover: true
});
jQuery(document).ready(function() {
var hash = window.location.hash.substr(1);
var href = jQuery('#nav2 li a').each(function(){
var href = jQuery(this).attr('href');
if(hash==href.substr(0,href.length-5)){
var toLoad = hash+'.html #content';
jQuery('#content').load(toLoad)
}
});
jQuery('#nav2 li a').click(function(){
jQuery("#nav2 li a").addClass("current").not(this).removeClass("current");
var toLoad = jQuery(this).attr('href')+' #content';
jQuery('#content').hide('fast',loadContent);
jQuery('#load').remove();
jQuery('#wrapper').append('<span id="load">LOADING...</span>');
jQuery('#load').fadeIn('normal');
window.location.hash = jQuery(this).attr('href').substr(0,jQuery(this).attr('href').length-5);
function loadContent() {
jQuery('#content').load(toLoad,'',showNewContent())
}
function showNewContent() {
jQuery('#content').show('normal',hideLoader());
}
function hideLoader() {
jQuery('#load').fadeOut('normal');
}
return false;
});
});
and this is the pages in question that im having trouble with.
Climate Page
You will see the Ajax loader at the bottom of the page with a secondary menu list.
I'm desperate guys, please help...
I had the same issue, couldn't get this to work:
$("#my_div").load('some-ajax-file.php', Cufon.refresh);
But, wrapping Cufon.refresh in a function did the trick:
$("#my_div").load('some-ajax-file.php', function() { Cufon.refresh(); });
this worked for me...
$(document).ajaxSuccess(function() {
Cufon.refresh();
});
You could try this:
function showNewContent() {
Cufon.refresh();
jQuery('#content').show('normal',hideLoader());
}
This is also discussed in the cufon api docs - https://github.com/sorccu/cufon/wiki/API
After ajax response you can simply use
Cufon.refresh();
That will reload cufon font style
Try adding this:
$(document).ajaxSuccess(function() {
Cufon('h2'); // or whatever other cufon calls, really...
});
$(document).ajaxSuccess(function() { Cufon.refresh(); });
Hope it helps :)
I had same problem, and to make faster resolution made an in-line CSS
<h5 style="font-family:xxx, Helvetica, sans-serif"></h5>
<style type="text/css">
#font-face {
font-family: SWZ721C;
src: url('../../includedfiles/xxx.TTF');
}
#font-face {
font-family: MyCustomFont;
src: url("../../includedfiles/xxx.eot") /* EOT file for IE */
}
</style>
I am trying to display an ajax spinner when loading AJAX content.
The following code appears to work fine in Firefox but not in IE7. The functions to show and hide the spinner are being called but the browser just does not display it.
Here is the jQuery:
$.ajax({
url: filterorSearch,
data: {filterParams: JSON.stringify(filters), requestTime: new Date().getTime()},
beforeSend: function(){
showLoadingGraphic();
},
complete: function(){
hideLoadingGraphic();
},
success: function(data){
$("#BreakingNews").html(data);
GetRelatedarticles();
}
});
function showLoadingGraphic() {
alert("show");
var showSpinner = $('#page-placeholder-wrapper #main-left').prepend('<div id="ajaxLoader"></div>');
return showSpinner;
}
function hideLoadingGraphic() {
alert("hide");
var hideSpinner = $('#ajaxLoader').remove();
return hideSpinner;
}
And the associated CSS for the spinner:
#page-placeholder-wrapper #main-left
{
position:relative;
}
#ajaxLoader
{
background:rgba(255,255,255,.7) url("../images/icon-ajax-loading.gif") no-repeat center center;
height:100%;
left:0;
position:absolute;
top:0;
width:100%;
z-index:9999;
}
To get you working try this:
background: url("../images/icon-ajax-loading.gif") no-repeat center center rgba(255,255,255,.7);
I don't know why the rgba has to be last!
[EDIT]
IE does not support rgba, therefore with it starting on background: it errors and the rest of the line isn't executed for the css
See: Browser Support for RGBa
JQuery actually fires events when it's doing ajax.
$(document).ajaxStart(function(){
$('#ajaxIndicator').show();
}).ajaxStop(function(){
$('#ajaxIndicator').hide();
});
This will save you a lot of time over manually doing it for each individual call.
You could have a DIV relative to the top of the document which you can show/hide which overlays everything else on the page. (I forget the exact CSS which makes it always be 200px from the top of the screen, etc) update: I think it's position:fixed, although I'm not sure how well this will work in IE.
<body>
<div id="ajaxIndicator" style="position:fixed; top:200px; text-align:center">
<img src="../indicator.gif" /> Loading ...
</div>
...
Might be problems with Z sorting of your DOM elements;
IE handles Z sorting of objects in a bit different way then other browsers. Try setting z-index on your wrapper element and it should help. Generally it's a best practice if you want to save you troubles with elements positioned with relatie or absolute positioning to always give their parent proper z-index;
Having the actual page to debug would make it easier.
For the sake of my sanity and getting this done today.
I have added the "ajaxLoader" element to the markup, hidden initially with CSS and then show/hide when AJAX starts/stops.
This works fine for all browsers.
Thanks to all for their input.