/*!
* moving boxes v2.3.4
* by chris coyier
* http://css-tricks.com/moving-boxes/
*/
/* �������������֮�� www.lanrenzhijia.com ת����ע������ */
/*jshint browser:true, jquery:true */
;(function($){
"use strict";
$.movingboxes = function(el, options){
// to avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var o, base = this;
// access to jquery and dom versions of element
base.$el = $(el).addclass('mb-slider');
base.el = el;
// add a reverse reference to the dom object
base.$el.data('movingboxes', base);
base.init = function(){
base.options = o = $.extend({}, $.movingboxes.defaultoptions, options);
// setup formatting (to reduce the amount of initial html)
base.$el.wrap('
');
// defaults
base.$window = base.$el.parent(); // mb-scroll
base.$wrap = base.$window.parent() // mb-wrapper
.prepend('')
.append('');
base.$panels = base.$el.children().addclass('mb-panel')
base.runtime = $('.mb-slider').index(base.$el) + 1; // get index (run time) of this slider on the page
base.regex = new regexp('slider' + base.runtime + '=(\\d+)', 'i'); // hash tag regex
base.initialized = false;
base.currentlymoving = false;
base.curpanel = (o.initanimation) ? 1 : base.gethash() || o.startpanel;
// save original slider width
base.width = (o.width) ? parseint(o.width,10) : base.$el.width();
// save panel width, o.panelwidth originally a fraction (0.5 of o.width) if defined, or get first panel width
// now can be set after initialization to resize using fraction (value <= 2) or px (all values > 2)
base.pwidth = (o.panelwidth) ? (o.panelwidth <=2 ? o.panelwidth * base.width : o.panelwidth) : base.$panels.eq(0).width();
// set up click on left/right arrows
base.$left = base.$wrap.find('.mb-left').click(function(){
base.goback();
return false;
});
base.$right = base.$wrap.find('.mb-right').click(function(){
base.goforward();
return false;
});
// code to run to update movingboxes when the number of panels change
base.update({}, false);
// make sure current panel is centered
base.setwrap(base.curpanel);
// go to clicked panel
base.$el.delegate('.mb-panel', 'click', function(e){
if (!$(this).hasclass(o.currentpanel)) {
e.preventdefault(); // prevent non-current panel links from working
base.change( base.$panels.index($(this)) + base.adj, {}, true );
}
});
// activate moving box on click or when an internal link obtains focus
base.$wrap.click(function(){
if (!base.$wrap.hasclass('mb-active-slider')) {
base.active();
}
});
base.$panels.delegate('a', 'focus' ,function(e){
e.preventdefault();
// focused link centered in moving box
var loc = base.$panels.index($(this).closest('.mb-panel')) + base.adj;
if (loc !== base.curpanel){
base.change( loc, {}, true );
}
});
// add keyboard navigation
$(document).keyup(function(e){
// ignore arrow/space keys if inside a form element
if (e.target.tagname.match('textarea|input|select')) { return; }
switch (e.which) {
case 39: case 32: // right arrow & space
if (base.$wrap.is('.mb-active-slider')){
base.goforward();
}
break;
case 37: // left arrow
if (base.$wrap.is('.mb-active-slider')){
base.goback();
}
break;
}
});
// bind events
$.each('preinit initialized initchange beforeanimation completed'.split(' '), function(i,evt){
if ($.isfunction(o[evt])){
base.$el.bind(evt + '.movingboxes', o[evt]);
}
});
base.$el.trigger( 'preinit.movingboxes', [ base, base.curpanel ] );
};
// update the panel, flag is used to prevent events from firing
base.update = function(callback, flag){
// infinite loop
base.$el.children('.cloned').remove();
base.$panels = base.$el.children();
base.adj = (o.wrap && base.$panels.length > 1) ? 0 : 1; // count adjustment for infinite panels
base.width = (o.width) ? parseint(o.width,10) : base.width;
base.$wrap.css('width', base.width); // set wrapper width
if (o.wrap && base.$panels.length > 1) {
base.$el.prepend( base.$panels.filter(':last').clone().addclass('cloned') );
base.$el.append( base.$panels.filter(':first').clone().addclass('cloned') );
base.$el.find('.cloned').each(function(){
// disable all focusable elements in cloned panels to prevent shifting the panels by tabbing
$(this).find('a,input,textarea,select,button,area').removeattr('name').attr('disabled', 'disabled');
$(this).find('[id]').andself().removeattr('id');
});
}
// set up panes & content sizes
// defined $panels again to include cloned panels
base.$panels = base.$el.children()
.addclass('mb-panel')
// inner wrap of each panel
.each(function(){
if ($(this).find('.mb-inside').length === 0) {
$(this).wrapinner('');
}
});
base.totalpanels = base.$panels.filter(':not(.cloned)').length; // don't include cloned panels in total
// in case current panel no longer exists
if (base.totalpanels <= 1) { base.curpanel = 1; }
base.setsizes(flag);
base.buildnav();
base.change(base.curpanel, callback, flag); // initialize from first panel... then scroll to start panel
// check panel height after all images load
base.imagesloaded(function(){
base.setsizes(false);
base.setwrap(base.curpanel);
// animate to chosen start panel - starting from the first panel makes it look better
if (!base.initialized){
settimeout(function(){
base.initialized = true;
base.change(base.gethash() || o.startpanel, {}, false);
base.$el.trigger( 'initialized.movingboxes', [ base, base.curpanel ] );
}, o.speed * 2 );
}
});
};
base.setsizes = function(flag){
// include padding & margins around the panels
base.padding = parseint(base.$panels.css('padding-left'), 10) + parseint(base.$panels.css('margin-left'), 10);
// save 'cur' numbers (current larger panel size), use stored sizes if they exist
base.curwidth = (o.panelwidth) ? (o.panelwidth <=2 ? o.panelwidth * base.width : o.panelwidth) : base.pwidth;
// save 'reg' (reduced size) numbers
base.regwidth = base.curwidth * o.reducedsize;
// set image heights so base container height is correctly set
base.$panels.css({ width: base.curwidth,margintop: '100' }); // make all panels big
// save each panel height... script will resize container as needed
// make sure current panel css is applied before measuring
base.$panels.eq(base.curpanel - base.adj).addclass(o.currentpanel);
base.heights = base.$panels.css('height','auto').map(function(i,e){ return $(e).outerheight(true); }).get();
base.returntonormal(base.curpanel, 0); // resize new panel, animation time
base.growbigger(base.curpanel, 0, flag);
base.updatearrows(base.curpanel);
// make base container wide enough to contain all the panels
base.$el.css({
position : 'absolute',
// add a bit more width to each box (base.padding *2; then add 1/2 overall width in case only one panel exists)
width : (base.curwidth + base.padding * 2) * base.$panels.length + (base.width - base.curwidth) / 2,
height : math.max.apply( this, base.heights ) + 10,
// add padding so scrollleft = 0 centers the left-most panel (needed because scrollleft cannot be < 0)
'padding-left' : (base.width - base.curwidth) / 2
});
base.$window.css({ height : (o.fixedheight) ? math.max.apply( this, base.heights ) : base.heights[base.curpanel - base.adj] });
};
// creates the numbered navigation links
base.buildnav = function() {
if (base.$nav) {
base.$nav.find('.mb-links').empty();
} else {
base.$nav = $('
').appendto(base.$wrap);
}
if (o.buildnav && base.totalpanels > 1) {
var t, j, a = '', $a;
base.$panels.filter(':not(.cloned)').each(function(i){
j = i + 1;
a = '';
$a = $(a);
// if a formatter function is present, use it
if ($.isfunction(o.navformatter)) {
t = o.navformatter(j, $(this));
if (typeof(t) === "string") {
$a.html(t);
} else {
$a = $('', t);
}
} else {
$a.html(j);
}
$a
.appendto(base.$nav.find('.mb-links'))
.addclass('mb-link mb-panel' + j)
.data('index', j);
});
base.$nav
.find('a.mb-link').bind('click', function() {
base.change( $(this).data('index') );
return false;
});
}
};
// resize panels to normal
base.returntonormal = function(num, time){
var panels = base.$panels.not(':eq(' + (num - base.adj) + ')').removeclass(o.currentpanel);
if (o.reducedsize === 1) {
panels.css({ width: base.regwidth }); // excluding fontsize change to prevent video flicker
} else {
panels.stop(true,false).animate({ width: base.regwidth,margintop:'100' }, (time === 0) ? 0 : o.speed);
}
};
// zoom in on selected panel
base.growbigger = function(num, time, flag){
var panels = base.$panels.eq(num - base.adj);
if (o.reducedsize === 1) {
panels.css({ width: base.curwidth }); // excluding fontsize change to prevent video flicker
// time delay prevents click outer panel from following links - fixes issue #67
settimeout(function(){
base.completed(num, flag);
}, (time === 0) ? 0 : o.speed);
} else {
panels.stop(true,false).animate({ width: base.curwidth,margintop:'0' }, (time === 0) ? 0 : o.speed, function(){
base.completed(num, flag);
});
}
};
// instantly center the indicated panel
base.setwrap = function(panel){
if (base.totalpanels >= 1) {
base.growbigger(panel, 0, false);
var leftvalue = base.$panels.eq(panel - base.adj).position().left - (base.width - base.curwidth) / 2 + base.padding;
base.$window.scrollleft(leftvalue);
}
};
base.completed = function(num, flag){
// add current panel class after animating in case it has sizing parameters
var loc = base.$panels.eq(num - base.adj);
if (!loc.hasclass('cloned')) { loc.addclass(o.currentpanel); }
if (flag !== false) { base.$el.trigger( 'completed.movingboxes', [ base, num ] ); }
};
// go forward/back
base.goforward = function(callback){
if (base.initialized) {
base.change(base.curpanel + 1, callback);
}
};
base.goback = function(callback){
if (base.initialized) {
base.change(base.curpanel - 1, callback);
}
};
// change view to display selected panel
base.change = function(curpanel, callback, flag){
if (base.totalpanels < 1) {
if (typeof(callback) === 'function') { callback(base); }
return;
}
var ani, leftvalue, wrapped = false;
flag = flag !== false;
// check if curpanel is a jquery selector or object
// $('' + curpanel) needed because $(3) = [3], but $('3') = []
if ($('' + curpanel).length || (curpanel instanceof $ && $(curpanel).length)) {
curpanel = $(curpanel).closest('.mb-panel').index() + base.adj;
} else {
// make sure it's a number and not a string
curpanel = parseint(curpanel, 10);
}
if (base.initialized && flag) {
// make this moving box active
if (!base.$wrap.hasclass('mb-active-slider')) { base.active(); }
// initchange event - has extra parameter with targeted panel (not cleaned)
base.$el.trigger( 'initchange.movingboxes', [ base, curpanel ] );
}
// make infinite scrolling work
if (o.wrap) {
if (curpanel > base.totalpanels) {
wrapped = true;
curpanel = 1;
base.returntonormal(0, 0);
base.setwrap(0);
} else if (curpanel === 0) {
wrapped = false;
curpanel = base.totalpanels;
base.setwrap(curpanel + 1);
}
}
if ( curpanel < base.adj ) { curpanel = (o.wrap) ? base.totalpanels : 1; }
if ( curpanel > base.totalpanels - base.adj ) { curpanel = (o.wrap) ? 1 : base.totalpanels; }
// abort if panel is already animating
// animation callback needed to clear this flag, but there is no animation before base.initialized is set
if (base.curpanel !== curpanel && (!base.currentlymoving || !base.initialized)) {
// set animation flag; animation callback will clear this flag
base.currentlymoving = !o.stopanimation;
// center panel in scroll window
base.$curpanel = base.$panels.eq(curpanel - base.adj);
leftvalue = base.$curpanel.position().left - (base.width - base.curwidth) / 2 + base.padding;
// when scrolling right, add the difference of the larger current panel width
if (base.initialized && (curpanel > base.curpanel || wrapped)) { leftvalue -= ( base.curwidth - base.regwidth ); }
ani = (o.fixedheight) ? { scrollleft : leftvalue } : { scrollleft: leftvalue, height: base.heights[curpanel - base.adj] };
base.curpanel = curpanel;
// before animation trigger
if (base.initialized && flag) { base.$el.trigger( 'beforeanimation.movingboxes', [ base, curpanel ] ); }
if (o.delaybeforeanimate) {
// delay starting slide animation
settimeout(function(){
base.animateboxes(curpanel, ani, flag, callback);
}, parseint(o.delaybeforeanimate, 10) || 0);
} else {
base.animateboxes(curpanel, ani, flag, callback);
}
} else {
base.endanimation();
}
};
base.animateboxes = function(curpanel, ani, flag, callback){
// animate the panels
base.$window.scrolltop(0).stop(true,false).animate( ani,
{
queue : false,
duration : o.speed,
easing : o.easing,
complete : function(){
if (base.initialized) {
base.$window.scrolltop(0); // opera fix - otherwise, it moves the focus link to the middle of the viewport
}
base.currentlymoving = false;
if (typeof(callback) === 'function') { callback(base); }
}
}
);
base.returntonormal(curpanel);
base.growbigger(curpanel, o.speed, flag);
base.updatearrows(curpanel);
if (o.hashtags && base.initialized) { base.sethash(curpanel); }
base.endanimation();
};
base.endanimation = function(){
// update navigation links
if (o.buildnav && base.$nav.length) {
base.$nav.find('a.mb-link')
.removeclass(o.currentpanel)
.eq(base.curpanel - 1).addclass(o.currentpanel);
}
};
base.updatearrows = function(cur){
base.$left.toggleclass(o.disabled, (!o.wrap && cur === base.adj) || base.totalpanels <= 1);
base.$right.toggleclass(o.disabled, (!o.wrap && cur === base.totalpanels) || base.totalpanels <= 1);
};
// this method tries to find a hash that matches an id and slider-x
// if either found, it tries to find a matching item
// if that is found as well, then it returns the page number
base.gethash = function(){
var h = window.location.hash,
i = h.indexof('&'),
n = h.match(base.regex);
// test for "/#/" or "/#!/" used by the jquery address plugin - $('#/') breaks jquery
if (n === null && !/^#&/.test(h) && !/#!?\//.test(h)) {
// #quote2&panel1-3&panel3-3
h = h.substring(0, (i >= 0 ? i : h.length));
// ensure the element is in the same slider
n = ($(h).length && $(h).closest('.mb-slider')[0] === base.el) ? $(h).closest('.mb-panel').index() + base.adj : null;
} else if (n !== null) {
// #&panel1-3&panel3-3
n = (o.hashtags) ? parseint(n[1],10) : null;
}
return (n > base.totalpanels) ? null : n;
};
// set hash tags
base.sethash = function(n){
var s = 'slider' + base.runtime + "=",
h = window.location.hash;
if ( typeof h !== 'undefined' ) {
window.location.hash = (h.indexof(s) > 0) ? h.replace(base.regex, s + n) : h + "&" + s + n;
}
};
// make moving box active (for keyboard navigation)
base.active = function(){
$('.mb-active-slider').removeclass('mb-active-slider');
base.$wrap.addclass('mb-active-slider');
};
// get: var currentpanel = $('.slider').data('movingboxes').currentpanel(); // returns # of currently selected/enlarged panel
// set: var currentpanel = $('.slider').data('movingboxes').currentpanel(2, function(){ alert('done!'); }); // returns and scrolls to 2nd panel
base.currentpanel = function(panel, callback){
if (typeof(panel) !== 'undefined') {
base.change(panel, callback); // parse in case someone sends a string
}
return base.curpanel;
};
// based on https://github.com/mottie/imagesloaded plugin
base.imagesloaded = function(callback, img) {
var i, ic,
c = true, // complete flag
t = img ? $(img) : base.$panels.find('img'),
l = t.length;
img = img || []; // array of images that didn't complete
for ( i = 0; i < l; i++ ) {
if (t[i].tagname === "img") {
// ie: filesize property = -1 before image has loaded & if image load error, so if false is returned
// 10x, then just assume it's an error & call it complete - it's what firefox & webkit does
ic = ('filesize' in t[i] && t[i].filesize < 0 && t[i].count > 10) ? true : t[i].complete;
// complete flag, checks previous flag status, complete flag & image height
// image height may need to be > 20 (or whatever the line-height is) because the alt text is included
c = (c && ic && t[i].height !== 0); // complete flag
// save non-complete images for next iteration
if (ic === false) {
img.push(t[i]);
// iteration count for ie
t[i].count = (t[i].count || 0) + 1;
}
}
}
if (c) {
// all complete, run the callback
if (typeof callback === "function") { callback(); }
} else {
// some images not loaded, rinse & repeat
settimeout(function(){
base.imagesloaded(callback, img);
}, 200);
}
};
// run initializer
base.init();
};
$.movingboxes.defaultoptions = {
// appearance
startpanel : 1, // start with this panel
reducedsize : 0.8, // non-current panel size: 80% of panel size
fixedheight : false, // if true, slider height set to max panel height; if false, slider height will auto adjust.
// behaviour
initanimation: true, // if true, movingboxes will initialize, then animate into the starting slide (if not the first slide)
stopanimation: false, // if true, movingboxes will force the animation to complete immediately, if the user selects the next panel
hashtags : true, // if true, hash tags are enabled
wrap : false, // if true, the panel will loop through the panels infinitely
buildnav : false, // if true, navigation links will be added
navformatter : null, // function which returns the navigation text for each panel
easing : 'swing', // anything other than "linear" or "swing" requires the easing plugin
// times
speed : 500, // animation time in milliseconds
delaybeforeanimate : 0, // time to delay in milliseconds before movingboxes animates to the selected panel
// selectors & classes
currentpanel : 'current', // current panel class
tooltipclass : 'tooltip', // added to the navigation, but the title attribute is blank unless the link text-indent is negative
disabled : 'disabled',// class added to arrows that are disabled (left arrow when on first panel, right arrow on last panel)
// callbacks
preinit : null, // callback after the basic movingboxes structure has been built; before "initialized"
initialized : null, // callback when movingboxes has completed initialization; all images loaded
initchange : null, // callback upon change panel initialization
beforeanimation : null, // callback before any animation occurs
completed : null // callback after animation completes
// deprecated options - but still used to keep the plugin backwards compatible
// and allow resizing the overall width and panel width dynamically (i.e. on window resize)
// width : 800, // overall width of movingboxes (not including navigation arrows)
// panelwidth : 0.5 // current panel width adjusted to 50% of overall width
};
$.fn.movingboxes = function(options, callback, flag){
var mb;
return this.each(function(){
mb = $(this).data('movingboxes');
// initialize the slider but prevent multiple initializations
if ((typeof(options)).match('object|undefined')){
if (mb && options instanceof $ && options.length) {
// pass a jquery object to change panels
mb.change(options, callback, flag);
} else if (mb) {
mb.update(callback, flag);
} else {
(new $.movingboxes(this, options));
}
} else if (mb) {
// page #, autoplay, one time callback, if flag is false then no events triggered and animation time = 0
mb.change(options, callback, flag);
}
});
};
// return the movingboxes object
$.fn.getmovingboxes = function(){
return this.data('movingboxes');
};
})(jquery);
/* �������������֮�� www.lanrenzhijia.com ת����ע������ */