Is there a simple way to show the spinner ($.mobile.showPageLoadingMsg()) on just one element/region ?
I'm loading this element's content via AJAX, so until it's finished I have to block it and show this spinner.
You can set the CSS position of the loading spinner to appear over a certain region. Here is a code example that both shows and hides the loading spinner over an element:
//this is an IIFE, it creates an enclosure around the code that separates it from global code
(function ($) {
//a flag so we know what state the loading spinner is in
var isShowing = false;
//this example is binding to all link elements
$('a').on('click', function () {
//check if the loading spinner is already showing
if (isShowing === false) {
//the loader is not showing, so create an overlay in the container element
var $con = $('#container').append('<div class="container-overlay"></div>');
//now position the loader over the container
$('.ui-loader').css({
position : 'absolute',
top : ($con.offset().top + ($con.height() / 2)),
left : ($con.offset().left + ($con.width() / 2))
});
//fade-in the overlay and show the loading spinner
$con.children('.container-overlay').fadeIn(500);
$.mobile.showPageLoadingMsg();
//set the flag so next time around we hide the spinner
isShowing = true;
} else {
//fade-out the overlay
$('#container').children('.container-overlay').fadeOut(500, function () {
//remove the overlay from the DOM
$(this).remove();
//hide the loader
$.mobile.hidePageLoadingMsg();
//reset the CSS of the loader element
$el.css({
position : 'fixed',
top : '50%',
left : '50%'
});
});
//set the flag so next time around we show the loading spinner
isShowing = false;
}
});
})(jQuery);
Here is a demo: http://jsfiddle.net/CkUZf/
For the demo (link) above, I used this CSS for the overlay element:
#container .container-overlay {
display : none;
height : 100%;
background : #000;
background : rgba(0, 0, 0, 0.75);
}
It would also be possible to append the loader element to whatever container you want to "load" but $.mobile.showPageLoadingMsg() automatically resets the loader element so you'd have to disable that code in the jQuery Mobile include (which is why I went this the lighter CSS version above).
Update
This is probably more like what you were thinking:
$.fn.customMobileSpinner = function (options) {
var defaults = {
url : null,
fadeDuration : 500,
bgColor : 'rgba(0, 0, 0, 0.75)',
bgColorFallback : '#000'
};
//merge the defaults and options objects
options = $.extend({}, defaults, options);
//make sure the URL is specified
if (options.url !== null) {
//only work with the first element passed-in
var $element = this.eq(0);
$element.append(
$('<div class="container-overlay" />').css({
display : 'none',
height : '100%',
width : '100%',
background : options.bgColorFallback,
background : options.bgColor
})
).children('.container-overlay').fadeIn(options.fadeDuration);
//update loader CSS
$('.ui-loader').css({
position : 'absolute',
top : ($element.offset().top + ($element.height() / 2)),
left : ($element.offset().left + ($element.width() / 2))
});
//show spinner
$.mobile.showPageLoadingMsg();
//create AJAX call
$.ajax({
url : options.url,
success : function (response) {
$element.fadeOut(options.fadeDuration, function () {
$element.html(response).fadeIn(options.fadeDuration);
$.mobile.hidePageLoadingMsg();
//reset loader CSS
$(".ui-loader").css({
position : 'fixed',
top : '50%',
left : '50%'
});
});
}
});
}
};
Then you just call this method on a jQuery object:
$('#some-container').customMobileSpinner({
url : 'some-url'
});
I'm afraid you can't. Take a look at the docs, you can just customize the message or hide the spinner, but not making it fit to a element.
If you just want to show a spinner on some element loading, use the beforeSend and complete options of the ajax method to hide/show it
Related
Here's what I'm trying to achieve:
Scrolling marquee content (with flexible length) makes a complete journey from right to left of the screen
Once it has disappeared off the screen, bring up some generic messages
In the background during generic messages, check for any new scrolling content and load it
Only when the generic messages have finished displaying, start scrolling again (if there is new content), otherwise repeat the generic messages
http://jsfiddle.net/Vbmm5/
(function($) {
$.fn.marquee = function(options) {
return this.each(function() {
var o = $.extend({}, $.fn.marquee.defaults, options),
$this = $(this),
$marqueeWrapper,
containerWidth,
animationCss,
elWidth;
o = $.extend({}, o, $this.data());
o.gap = o.duplicated ? o.gap : 0;
$this.wrapInner('<div class="js-marquee"></div>');
var $el = $this.find('.js-marquee').css({
'margin-right': o.gap,
'float':'left'
});
if(o.duplicated) {
$el.clone().appendTo($this);
}
$this.wrapInner('<div style="width:100000px" class="js-marquee-wrapper"></div>');
elWidth = $this.find('.js-marquee:first').width() + o.gap;
$marqueeWrapper = $this.find('.js-marquee-wrapper');
containerWidth = $this.width();
o.speed = ((parseInt(elWidth,10) + parseInt(containerWidth,10)) / parseInt(containerWidth,10)) * o.speed;
var animate = function() {
if(!o.duplicated) {
$marqueeWrapper.css('margin-left', o.direction == 'left' ? containerWidth : '-' + elWidth + 'px');
animationCss = { 'margin-left': o.direction == 'left' ? '-' + elWidth + 'px' : containerWidth };
}
else {
$marqueeWrapper.css('margin-left', o.direction == 'left' ? 0 : '-' + elWidth + 'px');
animationCss = { 'margin-left': o.direction == 'left' ? '-' + elWidth + 'px' : 0 };
}
$marqueeWrapper.animate(animationCss, o.speed , 'linear', function(){
getUpdates();
});
};
setTimeout(animate, o.delayBeforeStart);
});
};
})(jQuery);
$(function(){
$('#scrollerContent').marquee({
speed: 3000,
gap: 50,
delayBeforeStart: 0,
direction: 'right',
duplicated: false,
pauseOnHover: false,
});
});
function getUpdates()
{
alert("Hello"); // This is where the jQuery get function would be to update the text
alert("Show Details"); // This is where the generic details would be displayed
marquee();
}
The problem is the scrolling element requires a width, which obviously changes with every new 'load' of messages. I tried putting the getUpdates() function inside the main jQuery function, which does work almost perfectly but doesn't update the containerWidth variable, so messages longer than the original start half-way through, and shorter messages take ages to appear.
What I need is for the whole of the function to be re-run, including the re-setting of the width after the #scrollerText paragraph has been changed.
How do I do this?
If you had used console.log() instead of alert() you would have had the console open and seen
Uncaught ReferenceError: marquee is not defined
In getUpdates() you're calling a function marquee(); that does not exist. The script terminates there.
Go back a few steps (undoing what you've removed) and where the code triggers the animation, add the code to update the text before that, or if you're getting data you need to wrap that bit of code.
So, if you were getting data from the server, theurl.php would return text new text and nothing else. Move the code that triggers the animation to go again within the $.get callback function.
http://jsfiddle.net/Vbmm5/4/
$marqueeWrapper.animate(animationCss, o.speed , 'linear', function(){
// clear the text to prevent it from hanging at the end of the
// marquee while the script gets new data from the server
$this.find('#scrollerText').text('');
// get new text
$.get('theurl.php', function(response){
$this.find('#scrollerText').text(response);
// update the width
elWidth = $this.find('.js-marquee:first').width();
//fire event
$this.trigger('finished');
//animate again
if(o.pauseOnCycle) {
setTimeout(animate, o.delayBeforeStart);
}
else {
animate();
}
});
});
(the URL and post data in the example on jsfiddle is jsfiddle's way of returning html)
I've used $this.find('#scrollerText').text(response); even though there should be only one id and $('#scrollerText').text(response); would be fine. If you were to have multiple marquees you would target each marquee's text using $this.find, so if you want more than one use classes instead $this.find('.scrollerText').text(response);
I just found this tutorial on making an image cross fade transition with jquery.
The demo page works perfectly (jquery 1.2.3 used).
But when I apply the code to my site (jquery 10.1.0 embedded) it is not working...
When I embed the 1.2.3 version it works.
Anyone an idea whats wrong with the code?
here it comes:
// wrap as a jQuery plugin and pass jQuery in to our anoymous function
(function ($) {
$.fn.cross = function (options) {
return this.each(function (i) {
// cache the copy of jQuery(this) - the start image
var $$ = $(this);
// get the target from the backgroundImage + regexp
var target = $$.css('backgroundImage').replace(/^url|[\(\)'"]/g, '');
// nice long chain: wrap img element in span
$$.wrap('<span style="position: relative;"></span>')
// change selector to parent - i.e. newly created span
.parent()
// prepend a new image inside the span
.prepend('<img>')
// change the selector to the newly created image
.find(':first-child')
// set the image to the target
.attr('src', target);
// the CSS styling of the start image needs to be handled
// differently for different browsers
if ($.browser.msie || $.browser.mozilla) {
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : this.offsetTop
});
} else if ($.browser.opera && $.browser.version < 9.5) {
// Browser sniffing is bad - however opera < 9.5 has a render bug
// so this is required to get around it we can't apply the 'top' : 0
// separately because Mozilla strips the style set originally somehow...
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : "0"
});
} else { // Safari
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : ''
});
}
// similar effect as single image technique, except using .animate
// which will handle the fading up from the right opacity for us
$$.hover(function () {
$$.stop().animate({
opacity: 0
}, 250);
}, function () {
$$.stop().animate({
opacity: 1
}, 250);
});
});
};
})(jQuery);
// note that this uses the .bind('load') on the window object, rather than $(document).ready()
// because .ready() fires before the images have loaded, but we need to fire *after* because
// our code relies on the dimensions of the images already in place.
$(window).bind('load', function () {
$('img.fade').cross();
});
html is that:
<img class="fade" src="original.jpg" style="background: url(hover.jpg);" />
heres the link to the tutorial (dated 2008):
http://jqueryfordesigners.com/image-cross-fade-transition/
$.browser is not supported by new version of jQuery.
i'm developing a site where i use jQuery to achieve a faux columns effect. Here is a test page: http://goo.gl/IL3ZB . The left yellow <aside> height is set in java script with the height of the .body_container div. The height is set correctly for display.
The problem is when i do in Firefox 17 a full refresh (Shift + F5) the <aside> is displayed correctly, with the correct height, but the animation in js sees a much smaller height. When i then refresh the page normally, then java script also sees the correct height.
How can i resolve this problem?
Here is my js:
var floating_patents_bottom = 0;
$(window).load(function(){
$('.floating_patents').height( $('.body_container').height() );
floating_patents_bottom = ($('.body_container').height() > floating_patents_bottom ? $('.body_container').height() : floating_patents_bottom);
var toBottom = {
'top': floating_patents_bottom
};
});
var toTop = {
'position': 'absolute',
'top': '500px',
'display': 'none'
};
$(document).ready(function(){
$('.floating_patents').height( $('.body_container').height() );
floating_patents_bottom = ($('.body_container').height() > floating_patents_bottom ? $('.body_container').height() : floating_patents_bottom);
// floating_patents_bottom = $('.floating_patents').height();
var toBottom = {
'top': floating_patents_bottom
};
var patents = $(".floating_patents img");
patents.css(toTop);
patents.each(function(index) {
$(this).delay(index * 5000).css('margin','10px auto').fadeIn("slow").animate(toBottom , 15000, function(){
$(this).fadeOut("slow");
});
});
});
The problem is that when handler $(document).ready is called your images in content aren't fully loaded and have zero dimensions, so your $('.body_container').height() calculated incorrectly (the calculations sometimes happens correctly when browser takes images from the cache). The easiest solution for you is to move all code inside $(window).load handler.
A little refactored code which will work:
function floatingPatents() {
// find required elements in DOM
var patentsBlock = $('.floating_patents'), bodyContainer = $('.body_container');
var patents = patentsBlock.find('img').hide();
var floating_patents_bottom = 0;
// wait for complete page load
$(window).load(function(){
// resize holder
floating_patents_bottom = bodyContainer.height();
patentsBlock.height( floating_patents_bottom );
// calculate offsets
var toTop = {
position: 'absolute',
top: '500px',
display: 'none'
};
var toBottom = {
top: floating_patents_bottom
};
// start animation
patents.show().css(toTop).each(function(index) {
$(this).delay(index * 5000).css('margin','10px auto').fadeIn("slow").animate(toBottom , 15000, function(){
$(this).fadeOut("slow");
});
});
});
}
// run code when page ready
$(floatingPatents);
The document is ready before all of its elements are loaded. You're getting the correct height on the $(window).load event, but you're initializing the animations in the $(document).ready event. Just move everything into $(window).load and you should be good.
If waiting for the window to finish loading is too long (since otherwise, you won't be able to get the proper height of your .body-container div), you might be able to try this technique for getting placeholders for your images, so that the flow is correct before they've actually loaded.
http://andmag.se/2012/10/responsive-images-how-to-prevent-reflow/
this kind of emergency, so please, can someone help me...
I'm using movingboxes plugin for slideshow(this is the original plugin:http://css-tricks.com/moving-boxes/)
I need help with setting callback function add to the end of animation. I need to add fading effect, when currentSlidecomplete sliding,it should start fading into another view of the same image, for example,surrentSlide src is images/dr1.jpg and i need it to fade to images/dr1b.jpg and come back to images/dr1.jpg. looping through each current Slide
something like
completed :
function(e, slider, tar){
//fading for each currentSlide goes here;//
}
Something like you describe is already in the documentation
see the documentation here [1] and more specifically here [2].
EDIT: check jsfiddle here, i used a jquery add-on http://jsfiddle.net/r6yWC/157/
the add-on is here http://jqueryfordesigners.com/image-cross-fade-transition/
I also edited the code section below. I added the class "fade" to the img tag like this:
<img class="fade" src="http://chriscoyier.github.com/MovingBoxes/demo/4.jpg" alt="picture" style="background: url(http://chriscoyier.github.com/MovingBoxes/demo/2.jpg);"/>
In the 2nd link you will find a movingBoxes sample with a completed callback.
(function ($) {
$.fn.cross = function (options) {
return this.each(function (i) {
// cache the copy of jQuery(this) - the start image
var $$ = $(this);
// get the target from the backgroundImage + regexp
var target = $$.css('backgroundImage').replace(/^url|[\(\)'"]/g, '');
// nice long chain: wrap img element in span
$$.wrap('<span style="position: relative;"></span>')
// change selector to parent - i.e. newly created span
.parent()
// prepend a new image inside the span
.prepend('<img>')
// change the selector to the newly created image
.find(':first-child')
// set the image to the target
.attr('src', target);
// the CSS styling of the start image needs to be handled
// differently for different browsers
if ($.browser.msie || $.browser.mozilla) {
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : this.offsetTop
});
} else if ($.browser.opera && $.browser.version < 9.5) {
// Browser sniffing is bad - however opera < 9.5 has a render bug
// so this is required to get around it we can't apply the 'top' : 0
// separately because Mozilla strips the style set originally somehow...
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : "0"
});
} else { // Safari
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : ''
});
}
// similar effect as single image technique, except using .animate
// which will handle the fading up from the right opacity for us
$$.hover(function () {
$$.stop().animate({
opacity: 0
}, 250);
}, function () {
$$.stop().animate({
opacity: 1
}, 250);
});
});
};
})(jQuery);
$('#slider').movingBoxes({
// **** Appearance ****
// start with this panel
...
...
//-----> here is your callback
// callback after animation completes
completed: function(e, slider, tar){
var img = slider.$panels.eq(tar).find('img');
img.cross();
img.stop().animate({opacity: 0}, 1250).delay(500).animate({opacity: 1}, 2550);
}
});
[1] https://github.com/chriscoyier/MovingBoxes/wiki
[2] http://jsfiddle.net/Mottie/r6yWC/2/
I have a site that displays items, 12 items per page and I can paginate through the pages using jquery. On the same page I implemented a the tooltip feature with qTip.
Hovering over the items some information appear. That works until I use the paginator to go to the next page.
The pagination reloads the content. But it has the same structure as when I refresh the page.
Here's my code:
$(document).ready(function() {
$(".cornerize").corner("5px");
$('a#verd').live('click', exSite);
$("a.tp").live('click', thumpsUp);
$("a#next").click(getProgramms);
$("a#previous").click(getProgramms);
$("a#page").each(function() {
$(this).click(getProgramms);
});
$('a.ppname[rel]').each(function(){
$(this).qtip( {
content : {url :$(this).attr('rel')},
position : {
corner : {
tooltip : 'leftBottom',
target : 'rightBottom'
}
},
style : {
border : {
width : 5,
radius : 10
},
padding : 10,
textAlign : 'center',
tip : true,
name : 'cream'
}
});
});
});
The html/dom does not change:
<a class="ppname" rel="link" href="#">...</a>
qTip takes from every a.ppname the rel value end loads the content.
This is happening because new elements are not automatically "qTiped" when they are loaded after page load. For regular events, you would have to use .live() instead of .bind().
This has been solved before (judging from the comment): Problem with qTip - Tips not showing because elements load after the script.
The correct way to do it is (from that answer):
$('a.ppname[rel]').live('mouseover', function() {
var target = $(this);
if (target.data('qtip')) { return false; }
target.qtip({
overwrite: false, // Make sure another tooltip can't overwrite this one without it being explicitly destroyed
show: {
ready: true // Needed to make it show on first mouseover event
},
content : {url :$(this).attr('rel')},
position : {
corner : {
tooltip : 'leftBottom',
target : 'rightBottom'
}
},
style : {
border : {
width : 5,
radius : 10
},
padding : 10,
textAlign : 'center',
tip : true,
name : 'cream'
});
target.trigger('mouseover');
});