How to show loading image on dropdown change event(SelectedIndexChange) - javascript

I have a dropdown and grid on my page.On change of dropdown value the grid gets refreshed.The data which is bind to the grid is fetched from the database.When I change dropdown value I should be able to see a loading image on my screen.After the data is loaded the loading image should disappear.How will I achieve this??
Any suggestion will be helpful..
Below is the code that I have used for submit click .How should I modify it to work on dropdown change event.
<script type="text/javascript">
function ShowProgress() {
setTimeout(function () {
var modal = $('<div />');
modal.addClass("modal");
$('body').append(modal);
var loading = $(".loading");
loading.show();
var top = Math.max($(window).height() / 2 - loading[0].offsetHeight / 2, 0);
var left = Math.max($(window).width() / 2 - loading[0].offsetWidth / 2, 0);
loading.css({ top: top, left: left });
}, 200);
}
$('form').live("submit", function () {
ShowProgress();
});

You can, of course, show it before making the request, and hide it after it completes:
Html :
<div id='loading-image'>
<img src='loadinggraphic.gif'/>
</div>
Script :
$('#loading-image').show();
$.ajax({
url: 'data.php',
cache: false,
success: function(data){
$('.info').html(data);
},
complete: function(){
$('#loading-image').hide();
}
});
Here, in data.php you can put your logic to fetch the data from the database.
I usually prefer the more general solution of binding it to the global ajaxStart and ajaxStop events, that way it shows up for all ajax events:
$('#loading-image').bind('ajaxStart', function(){
$(this).show();
}).bind('ajaxStop', function(){
$(this).hide();
});

Related

Load data on scrolling right

I created a page in which to view data we scroll on right instead of down. Now I tired to load data while scrolling instead of loading the entire page at first. I can work around if it is down scroll. This is the code that I'm working on:
$(document).ready(function() {
var win = $(window);
win.scroll(function() {
if ($(document).height() - win.height() == win.scrollTop())
{
$('#loading').show();
$.ajax({
url: 'load.php',
dataType: 'html',
success: function(html) {
$('#data').append(html);
$('#loading').hide();
}
});
}
});
});
I referred and worked on this code from here. Now i need to load data when I'm scrolling right. I tried taking the difference in width but it is not working. Is there any other work around ?
may be something like this ?
$(document).ready(function() {
$('ul').scroll(function(event) {
if (this.scrollWidth - this.clientWidth - this.scrollLeft < 50) {
$(this).append('<li>data 1</li><li>data 2</li><li>data 3</li><li>data 4</li>')
}
});
});

How do I properly delay jQuery animations when loading a remote HTML?

EDIT: This software package is the full and undoctored version of what I'm trying to fix here. The problem is in the /data/renderpage.js script. Feel free to examine this before continuing.
https://github.com/Tricorne-Games/HyperBook
I really appreciate all the help guys!
=
I am polishing a jQuery script to do the following in a rigid sequence...
Fade out the text.
Shrink the size of the container div.
Preload the remote HTML ///without showing it yet!///
Open the size of the container div.
Fade in the new remote HTML.
I do not mind if steps 1 and 2, 4 and 5 are combined to be one whole step (fade/resize at the same time). It's when the new HTML is loaded it interrupts the entire animation, even from the beginning.
The idea is that I do not want my remote HTML to show until after the animation renders right. I want the original text to fade out and the container div close up, then, behind the scenes, ready the text of the new HTML, and then have the container div open up and fade the new text in.
It seems when I call the load(url) function, it instantaneously loads the page up, and the animations are still running (like the new HTML ends up fading out, only to fade back in, and not the original text out and then the new one in). Either that, or the whole function is calling each line at the same time, and it's disrupting the page-changing effect I want.
Here's my current script setup...
$(document).ready(function() {
// Start-Up Page Load (Cover, ToC, etc.)
$('#content').load('pages/page1.htm');
// Navigating Pages
$(document).on('click', 'a', function(e) {
e.preventDefault();
var ahref = $(this).attr('href');
$('#content_container').animate({height: 'hide'}, 500);
$('#content').fadeTo('slow', 0.25);
$('#content').load(ahref);
$('#content').css({opacity: 0.0});
$('#content').fadeTo('slow', 1.0);
$('#content_container').animate({height: 'show'}, 500);
return false;
});
});
What is it wrong I'm doing here? I have used the delay() function on every one of those steps and it doesn't solve the problem of holding back the new text.
jQuery objects can provide a promise for their animation queues by calling .promise on the jQuery element.
You can wait on one or more of these to complete using $.when() and then perform other operations.
The following does a fade out and slide up in parallel with the load, then (only when the animations complete), slides it down then fades it in (in sequence):
$(document).on('click', 'a', function (e) {
e.preventDefault();
var ahref = $(this).attr('href')
var $container = $('#content_container');
var $content = $('#content');
// Slide up and fadeout at the same time
$container.animate({
height: 'hide'
}, 500);
$content.fadeOut();
// Load the content while fading out
$('#content').load(ahref, function () {
// Wait for the fade and slide to complete
$.when($container.promise(), $content.promise()).then(function () {
// Slide down and fadein (in sequence)
$container.animate({
height: 'show'
}, 500, function () {
$content.fadeTo('slow', 1.0);
});
});
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/3/
The only issue with this version is that the load may complete faster than the fadeout/slideup and show the new data too early. In this case you want to not use load, but use get (so you have control over when to insert the new content):
// Load the content while fading out
$.get(ahref, function (data) {
// Wait for the fade and slide to complete
$.when($container.promise(), $content.promise()).then(function () {
$content.html(data);
// Slide down and fadein (in sequence)
$container.animate({
height: 'show'
}, 500, function () {
$content.fadeTo('slow', 1.0);
});
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/4/
Notes:
return false from a click handler does the same as e.stopPropagation() and e.preventDefault(), so you usually only need one or the other.
I started with the JSFiddle from #Pete as no other sample was handy. Thanks Pete.
Update:
Based on the full code now posted, you are returning full pages (including header and body tags). If you change your code to .load(ahref + " #content" ) it will extract only the part you want. This conflicts with the second (better) example I provided which would need the pages returned to be partial pages (or extract the required part only).
Additional Update:
As $.get also returns a jQuery promise, you can simplify it further to:
$.when($.get(ahref), $container.promise(), $content.promise()).then(function (data) {
$content.html(data);
// Slide down and fadein (in sequence)
$container.animate({
height: 'show'
}, 500, function () {
$content.fadeTo('slow', 1.0);
});
});
The resolve values from each promise passed to $.when are passed to the then in order, so the first parameter passed will be the data from the $.get promise.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/11/
The issue is because you're not waiting for the hide animations to finish before loading the content, or waiting for the content to load before starting the show animations. You need to use the callback parameters of the relevant methods. Try this:
$(document).on('click', 'a', function(e) {
e.preventDefault();
var ahref = $(this).attr('href'),
$content = $('#content'),
$contentContainer = $('#content_container');
$contentContainer.animate({ height: 'hide'}, 500);
$content.fadeTo('slow', 0.25, function() {
// animation completed, load content:
$content.load(ahref, function() {
// load completed, show content:
$content.css({ opacity: 0.0 }).fadeTo('slow', 1.0);
$contentContainer.animate({ height: 'show' }, 500);
});
});
});
Note that for the effect to work the most effectively on the UI you would need to perform the load() after the animation which takes the longest to complete has finished.
Instead of using the load() function, you can use the get() function and its callback paramater to save the HTML into a variable before actually putting it into the element with html().
After doing all the animations to fade out and close the old box (and maybe inside an animation-finished callback function) you'll want to use something like the following:
$.get(ahref, function(data) {
// JQuery animation before we want to see the text.
$('#content').html(data); // actually inserts HTML into element.
// JQuery animation to fade the text in.
});
Using a bunch of the code everyone posted here, I rewrote the segment I originally had to follow suit. This is now my working result.
$(document).ready(function() {
// Start-Up Page Load (Cover, ToC, etc.)
$('#content').load('pages/page1.htm');
// Navigating Pages
$(document).on('click', 'a', function(e) {
e.preventDefault();
var ahref = $(this).attr('href');
$('#content').fadeTo('slow', 0.0)
$('#content_container').animate({height: 'hide'}, 500, function(){
$('#content').load(ahref + '#content', function(){
$('#content_container').animate({height: 'show'}, 500, function(){
$('#content').fadeTo('slow', 1.0);
});
});
});
return false;
});
});
You can use deferred or callbacks function
$(document).on('click', 'a', function(e) {
e.preventDefault();
var ahref = $(this).attr('href');
var dfd1 = $.Deferred();
var dfd2 = $.Deferred();
var dfd3 = $.Deferred();
var dfd4 = $.Deferred();
$('#content_container').animate({height: 'hide'}, 500, function(){
dfd1.resolve();
});
dfd1.done(function() {
$('#content').fadeTo('slow', 0.25, function() {
dfd2.resolve();
});
});
dfd2.done(function() {
$('#content').load(ahref, function() {
$('#content').css({opacity: 0.0});
dfd3.resolve();
});
});
dfd3.done(function() {
$('#content').fadeTo('slow', 1.0, function() {
dfd4.resolve();
});
});
dfd4.done(function() {
$('#content_container').animate({height: 'show'}, 500);
});
return false;
});

Wait for document mousedown to complete before element onclick can start

I have a panel that slides open on an element click called "details" and populates the panel via ajax depending on the data attribute value. I also have it setup that if you close outside that panel, it will close. If the panel is open and the user clicks on a different "details" element, I want the panel to close and open again populated with the data from the new data attribute.
Problem is that the codes checks if the panel is visible and won't load the ajax if it is. How can I change this so the click event knows the mousedown event is completed before it does it's thing?
// SLIDING PANEL
$(".details").on("click", function(e){
e.preventDefault();
var panel = $("#DetailsPanel");
var mkey = $(this).data("masterkey-id");
var _self = $(this);
// fetch data ONLY when panel is hidden...
// otherwise it fetches data when the panel is closing
if (!panel.is(':visible')) {
panel.load("/com/franchise/leads.cfc?method=getLeadDetails", { mkey: mkey }, function(response, status, xhr) {
// if the ajax source wasn't loaded properly
if (status !== "success") {
var msg = "<p>Sorry, but there was an error loading the document.</p>";
panel.html(msg);
};
// this is part of the .load() callback so it fills the panel BEFORE opening it
panel.toggle("slide", { direction: "right" }, "fast", function(){
_self.parent().parent().addClass("warning");
});
});
} else {
panel.toggle("slide", { direction: "right" }, "fast", function(){
_self.parent().parent().removeClass("warning");
});
};
return false;
});
$(document).on("mousedown", function(){
$("#DetailsPanel").hide("slide", { direction: "right" }, "fast", function(){
//_self.parent().parent().removeClass("warning");
});
});
// don't close panel when clicking inside it
$(document).on("mousedown","#DetailsPanel",function(e){e.stopPropagation();});
$(document).on("click", "#ClosePanel", function(){
$("#DetailsPanel").hide("slide", { direction: "right" }, "fast", function(){
$("#LeadsTable tr").removeClass("warning");
});
});
// END SLIDING PANEL
Setting a timeout worked for me in another context:
onclick="window.setTimeout( function(){ DO YOUR STUFF }, 2);"
This solves many problems of this type.
I'm not totally sure about this but if you use "mouseup" instead "click" could work as you expect. Try it and let me know if I'm wrong.
Ok, so I found this little nugget http://www.gmarwaha.com/blog/2009/06/09/jquery-waiting-for-multiple-animations-to-complete/ and it works pretty good. No issues so far.
Here is the new code
$(".details").on("click", function(e){
e.preventDefault();
var panel = $("#DetailsPanel");
var mkey = $(this).data("masterkey-id");
var _self = $(this);
// fetch data ONLY when panel is hidden...
// otherwise it fetches data when the panel is closing
var wait = setInterval(function() {
if( !$("#DetailsPanel").is(":animated") ) {
clearInterval(wait);
// This piece of code will be executed
// after DetailsPanel is complete.
if (!panel.is(':visible')) {
panel.load("/com/franchise/leads.cfc?method=getLeadDetails", { mkey: mkey }, function(response, status, xhr) {
// if the ajax source wasn't loaded properly
if (status !== "success") {
var msg = "<p>Sorry, but there was an error loading the document.</p>";
panel.html(msg);
};
// this is part of the .load() callback so it fills the panel BEFORE opening it
panel.toggle("slide", { direction: "right" }, "fast", function(){
_self.parent().parent().addClass("warning");
});
});
} else {
panel.toggle("slide", { direction: "right" }, "fast", function(){
_self.parent().parent().removeClass("warning");
});
};
}
}, 200);
return false;
});

tumblr audio + Masonry with infinite scroll- other solutions posted have confused me [duplicate]

Here's a test page: http://masonry-test.tumblr.com/
I'm using jquery Masonry with infinite scroll on tumblr. All is fine except with audio players. They won't load on the second page and display this message instead [Flash 9 is required to listen to audio.].
Did a little research and found a solution. One here (this one too) and here's the js from the Mesh theme that does that successfully (line 35).
Problem is I don't know where and how to implement it in my code. Everything I tried either wasn't working or it left a small gap around the masonry blocks. My code:
$(document).ready(function () {
var $container = $('.row');
$container.imagesLoaded(function () {
$container.masonry({
itemSelector: '.post',
columnWidth: 1
});
});
$container.infinitescroll({
navSelector: '#page-nav',
nextSelector: '#page-nav a',
itemSelector: '.post',
loading: {
finishedMsg: "No more entries to load.",
img: "http://static.tumblr.com/7wtblbo/hsDlw78hw/transparent-box.png",
msgText: "Loading..."
},
debug: true,
bufferPx: 5000,
errorCallback: function () {
$('#infscr-loading').animate({
opacity: 0.8
}, 2000).fadeOut('normal');
}
},
function (newElements) {
//tried this but doesn't work
/* repair video players*/
$('.video').each(function(){
var audioID = $(this).attr("id");
var $videoPost = $(this);
$.ajax({
url: '/api/read/json?id=' + audioID,
dataType: 'jsonp',
timeout: 50000,
success: function(data){
$videoPost.append('\x3cdiv class=\x22video_player_label\x22\x3e' + data.posts[0]['video-player'] +'\x3c/div\x3e');
}
}
});
});
/* repair audio players*/
$('.audio').each(function(){
var audioID = $(this).attr("id");
var $audioPost = $(this);
$.ajax({
url: '/api/read/json?id=' + audioID,
dataType: 'jsonp',
timeout: 50000,
success: function(data){
$audioPost.append('\x3cdiv class=\x22audio_player\x22\x3e' + data.posts[0]['audio-player'] +'\x3c/div\x3e');
}
}
});
});
var $newElems = $(newElements).css({
opacity: 0
});
$newElems.imagesLoaded(function () {
$newElems.animate({
opacity: 1
});
$container.masonry('appended', $newElems, true);
});
});
$(window).resize(function () {
$('.row').masonry();
});
});
By default the API will return a white audio player.
you can change it by using the jQuery method to replace the flash player with a black or white player respectively.
.replace("audio_player.swf", "audio_player_black.swf")
or simply change the color itself
.replace("color=FFFFFF", "color=EA9D23");
Example:
$('.audio').each(function(){
var audioID = $(this).attr("id");
var $audioPost = $(this);
$.ajax({
url: '/api/read/json?id=' + audioID,
dataType: 'jsonp',
timeout: 50000,
success: function(data){
$audioPost.append('\x3cdiv class=\x22audio_player\x22\x3e' + data.posts[0]['audio-player'].replace("audio_player.swf","audio_player_black.swf") +'\x3c/div\x3e');
}
}
});
I had a lot of trouble with this and hope it helps someone out. I found the above information here Change Tumblr audio player color with Javascript.
I noticed a few things and this is what I advise you to try:
For that script to work, the elements with the class "audio" should each have an "id" attribute with the post ID. The HTML should look like that:
<div class="audio" id={PostID}>{AudioPlayerWhite}</div>
Tumblr will automatically fill the {PostID} part with the ID for each post. I suppose it works in the same manner for videos (haven't tried it with videos yet).
As for position, I did it like this:
function (newElements) {
....
$newElems.imagesLoaded(function () {
....
});
//audio repair goes here!
}
Here is a solution I came up with when I needed to implement the same functionality in the template I was creating.
In your HTML, include your AudioPlayer Tumblr tag between comments. This is to prevent loaded scripts from being called. Also add a class "unloaded" to keep track whether or not we've loaded the audio player for this post or not.
...
{block:AudioPlayer}
<div class="audio-player unloaded">
<!--{AudioPlayerBlack}-->
</div>
{/block:AudioPlayer}
...
If you look at the commented code after the page is loaded, you will notice an embed tag being passed to one of the Tumblr javascript functions. Since we commented it, it will not execute. Instead we will want to extract this string and replace the div contents with it.
Create a javascript function which will do this. This can be done with regular javascript, but to save time I will do it with jQuery since this is how I did it for my template:
function loadAudioPosts() {
// For each div with classes "audio-player" and "unloaded"
$(".audio-player.unloaded").each(function() {
// Extract the <embed> element from the commented {AudioPlayer...} tag.
var new_html = $(this).html().substring(
$(this).html().indexOf("<e"), // Start at "<e", for "<embed ..."
$(this).html().indexOf("d>")+2 // End at "d>", for "...</embed>"
);
// Replace the commented HTML with our new HTML
$(this).html(new_html);
// Remove the "unloaded" class, to avoid reprocessing
$(this).removeClass("unloaded");
});
}
Call loadAudioPosts() once on page load, then every time your infinite scrolling loads additional posts.

How can i get both of these javascript files to work?

A the end of my index.html file I'm including two script files. One of files handles loading page content with jquery. The other file handles manipulating a tabbed content area on my home page, also jquery. If I put the file for the tabbed content area after the file for the ajax page load file, then tabs work but the ajax for the page load does not work. If I reverse the order of those files, then the page load ajax works but not the tabs. What could be causing this?
Here's the file for the tabbed content:
$(document).ready(function (){
initialize();
});
function initialize() {
//Click on nav to load external content through AJAX
// $('#topnav a').click(function(e){
// e.preventDefault();
// $('#pages').load( e.target.href + ' #loadcontent'); //pages finished loading
// }); //clicked on nav
$(function() {
$("#tabedarea").organicTabs();
$("tabedarea").organicTabs({
"speed": 200
});
});
}
(function($) {
$.organicTabs = function(el, options) {
var base = this;
base.$el = $(el);
base.$navtabs = base.$el.find(".navtabs");
base.init = function() {
base.options = $.extend({},$.organicTabs.defaultOptions, options);
// Accessible hiding fix
$(".hidetabs").css({
"position": "relative",
"top": 0,
"left": 0,
"display": "none"
});
base.$navtabs.delegate("li > a", "click", function() {
// Figure out current list via CSS class
var curList = base.$el.find("a.current").attr("href").substring(1),
// List moving to
$newList = $(this),
// Figure out ID of new list
listID = $newList.attr("href").substring(1),
// Set outer wrapper height to (static) height of current inner list
$allListWrap = base.$el.find(".list-wrap"),
curListHeight = $allListWrap.height();
$allListWrap.height(curListHeight);
if ((listID != curList) && ( base.$el.find(":animated").length == 0)) {
// Fade out current list
base.$el.find("#"+curList).fadeOut(base.options.speed, function() {
// Fade in new list on callback
base.$el.find("#"+listID).fadeIn(base.options.speed);
// Adjust outer wrapper to fit new list snuggly
//var newHeight = base.$el.find("#"+listID).height();
//$allListWrap.animate({
// height: newHeight
//});
// Remove highlighting - Add to just-clicked tab
base.$el.find(".navtabs li a").removeClass("current");
$newList.addClass("current");
});
}
// Don't behave like a regular link
// Stop propegation and bubbling
return false;
});
};
base.init();
};
$.organicTabs.defaultOptions = {
"speed": 300
};
$.fn.organicTabs = function(options) {
return this.each(function() {
(new $.organicTabs(this, options));
});
};
})(jQuery);
And here's the file for the page load ajax:
// remap jQuery to $
(function($){})(window.jQuery);
/* trigger when page is ready */
$(document).ready(function (){
initialize();
});
function initialize() {
//Click on nav to load external content through AJAX
$('#topnav a, #bottomnav a').not('#bottomnav #fbcallus a').click(function(e){
e.preventDefault();
$('#pages').load( e.target.href + ' #loadcontent'); //pages finished loading
}); //clicked on nav
//handle AJAX for left nav
}
You're creating global functions with the same name initialize change the names of those or just one. The one that's loaded afterwards overrides the first
The problem is having both the functions the same name. Use two different names for the functions.
Then you don't need to add two page load handlers. Add a single page load handler in the latter script and call the two methods in it.
suppose your two functions are initialize() and init2() then at the latter js file use
$(document).ready(function () {
initialize();
init2();
});

Categories

Resources