Modified 2009-05-19 to use a simpler technique to make it inline.

OK, one more flexcal transition, inspired by Stefan Petre's jQuery slot machine. I should have been balancing my checkbook, but my kids thought this was cooler.


$('#slots').flexcal({
	transition: function(o){ 
		var pane = o.elements.eq(1-o.currSlide), origTable = pane.find('table');
		o.elements.eq(o.currSlide).css({zIndex: 1}).animate({top: -o.$cont.height()}, 'normal', 'easeInBack');
		pane.css({top: o.$cont.height(), zIndex: 2}).show().animate({top: 0}, 'normal', 'easeInBack', function(){
			// make two identical tables without headers and position them correctly (lined up with the bottom)
			var spinners = tableSpinners (origTable, o.gif);
			var tables = origTable.clone().add(origTable.clone()).appendTo(pane).
				find('caption').remove().end().
				css({bottom: 0 , marginBottom: 0, zIndex: 101}).hide();
			function dropOne(){
				if (spinners.length == 0){
					tables.remove();
					return;
				}
				var spinner = spinners.eq(Math.floor(Math.random()*spinners.length));
				var h = spinner.height();
				var left = spinner.offset().left - origTable.offset().left;
				var right = left + spinner.width();
				spinners = spinners.not(spinner.remove());
				origTable.animate({foo: 0}, { // the {foo:0} seems necessary because we need to animate some property, even if it isn't real
					duration: o.duration,
					easing: 'easeOutElastic',
					step: function(now, fx){
						if (fx.state == 0){
							tables.show();
							fx.start = now = 0; 
							fx.end = 3*h; 
						}
						tables.eq(0).css(offsetColumn(right, left, h, now));
						tables.eq(1).css(offsetColumn(right, left, h, now-h));
					},
					complete: dropOne
				});
			}
			setTimeout (dropOne, o.duration);
		})
	}, 
	position: {at: 'top', my: 'top'},
	speed: 0,
	hideOnOutsideClick: false,
	transitionOptions: {
		duration: 1500,
		gif: '/images/ani-bw.gif'
	},
	// make room for the inline calendar
	shown: function() { $('#slots').height($('#slots').flexcal('box').height()); }
});
$('#slots').flexcal('around', 'commit', function(d){
	this.d = d;
	this.box().find('td a').removeClass('ui-state-active');
	this.box().find('td a[rel="'+$.ui.flexcal.date2string(d)+'"]').addClass('ui-state-active');
	this.element.val(this.format(d));
	this._trigger('commit', 0, d);
});
$('#slots').flexcal('show');

function tableSpinners(t, gif){
	var topRow = t.find('tr:first td, tr:first th'), botRow = t.find('tr:last td'), ret = [];
	for(var i = 0; i < topRow.length; ++i){
		var topCell = topRow.eq(i), botCell = botRow.eq(i);
		ret.push($('<img>').appendTo('body').css(topCell.offset()).
			css({
				paddingTop: '2px',
				paddingBottom: '2px',
				position: 'absolute', 
				width: botCell.outerWidth(true), 
				// hack to avoid Firefox table height bug
				height: t.find('tbody').height()+t.find('thead').height(),
				zIndex: 101
			}).
			attr('src', gif)[0]);
	}
	return $(ret);
}

// create a css object with bottom = b and clip set to rect(0 r h l) pixels, with
// the top and bottom of that rect offset by b so the clip rect is fixed on the screen
// and offsetting b if it is out of the range -h..h
function offsetColumn (r, l, h, b){
	b = b%(2*h)-h; // move b into range
	return {bottom: b, clip: ['rect(',b,'px ',r,'px ',b+h,'px ',l,'px)'].join('')};
}

The code also shows how to make the datepicker "inline".

Leave a Reply


Warning: Undefined variable $user_ID in /home/public/blog/wp-content/themes/evanescence/comments.php on line 75