/* ======================================================================== * vc: carousel.js v0.4.5 * fork bootstrap: carousel.js v3.0.0 * http://twbs.github.com/bootstrap/javascript.html#carousel * ======================================================================== * copyright 2012 twitter, inc. * * licensed under the apache license, version 2.0 (the "license"); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "as is" basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. * ======================================================================== */ ;(function($) { "use strict"; // carousel class definition // ========================= var carousel = function (element, options) { if($(window).width()<768 && $(element).hasclass("vc-carousel vc-slide")){ options.interval = 0; } if(!options.viewnum) options.viewnum=0; this.$element = $(element) this.$indicators = this.$element.find('.vc-carousel-indicators') this.options = options this.paused = this.sliding = this.interval = this.$active = this.$items = null this.options.pause == 'hover' && this.$element .on('mouseenter', $.proxy(this.pause, this)) .on('mouseleave', $.proxy(this.cycle, this)) this._build() // new } carousel.defaults = { mode: 'horizontal' , partial: false , interval: 5000 , pause: 'hover' , wrap: false , autoheight: true , perview: 1 , hideonend: false } carousel.prototype.cycle = function (e) { e || (this.paused = false) this.interval && clearinterval(this.interval) this.options&&this.options.interval && !this.paused && (this.interval = setinterval($.proxy(this.next, this), this.options.interval)) this.touch_start_position = 0; return this } carousel.prototype.getactiveindex = function () { this.$active = this.$element.find('.vc-item.vc-active') if(!this.$active.length) this.$active = this.$element.find('.vc-item:first').addclass('vc-active') this.$items = this.$active.parent().children() return this.$items.index(this.$active) } carousel.prototype.showhidecontrol = function(index) { if(typeof index === 'undefined') var index = this.getactiveindex() //this.$left_control[index===0 ? 'hide' : 'show']() //this.$right_control[index===this.items_count-1 ? 'hide' : 'show']() } carousel.prototype.to = function (pos) { var that = this var activeindex = this.getactiveindex() if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) return this.$element.one('slid', function () { that.to(pos) }) if (activeindex == pos) return this.pause().cycle() return this.slide(pos > activeindex ? 'next' : 'prev', $(this.$items[pos])) } carousel.prototype.pause = function (e) { e || (this.paused = true) if (this.$element && this.$element.find('.vc-next, .vc-prev').length && $.support.transition.end) { this.$element.trigger($.support.transition.end) this.cycle(true) } this.interval = clearinterval(this.interval) return this } carousel.prototype.next = function () { if (this.sliding) return return this.slide('next') } carousel.prototype.prev = function () { if (this.sliding) return return this.slide('prev') } carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.vc-item.vc-active') var $next = next || $active[type](); if(type=="prev" && $next.index() == -1 && this.options.viewnum>0){ $next = this.$element.find('.vc-item:eq("'+(this.items_count-this.options.viewnum*1)+'")'); } var iscycling = this.interval var direction = type == 'next' ? 'vc-left' : 'vc-right' var fallback = type == 'next' ? 'first' : 'last' var that = this if (!$next.length) { if (!this.options.wrap) { this.returnswipedslide() return } $next = this.$element.find('.vc-item')[fallback]() } this.sliding = true //mobile don't move if($(window).width()<768 && this.$element.hasclass("vc-carousel vc-slide")){ return; } iscycling && this.pause() var e = $.event('slide.vc.carousel', { relatedtarget: $next[0], direction: direction }) if ($next.hasclass('vc-active')) return if (this.$indicators.length) { this.$indicators.find('.vc-active').removeclass('vc-active') this.$indicators.find('.vc-partial').removeclass('vc-partial') this.$element.one('slid', function () { var index = that.getactiveindex(), $nextindicator = $(that.$indicators.children().slice(index, that.getactiveindex() + that.options.perview)) $nextindicator && $nextindicator.addclass('vc-active') that.options.partial && $nextindicator && (index+1 < that.items_count ? $nextindicator.last().next().addclass('vc-partial') : $nextindicator.first().prev().addclass('vc-partial')) if(that.options.hideonend) that.showhidecontrol(index) }) } this.current_index = $next.index() if(this.current_index > this.items_count-this.options.viewnum*1) { this.current_index = 0; } else if(this.current_index < 0) { this.current_index = this.items_count -1 } if(this.options.autoheight) { this.current_pos_value = -1 * this._step * this.current_index } else { this.current_pos_value = -1 * $next.position()[this.animation_position] } if(this.options.partial && this.current_index >= this.items_count-1) { this.current_pos_value += this._step*(1-this.partial_part) } if ($.support.transition && this.$element.hasclass('vc-slide')) { this.$element.trigger(e) if (e.isdefaultprevented()) return this.$slideline_inner .addclass('vc-transition') .css(this.animation_position, this.current_pos_value + that.pos_units) if(!this.options.autoheight) this.recalculateslidelineheight($next.height(), true) this.$slideline_inner.one($.support.transition.end, function(){ $next.addclass('vc-active') $active.removeclass('vc-active') that.$slideline_inner.removeclass([type, 'vc-transition'].join(' ')) that.sliding = false that.removeswipeanimationspeed() settimeout(function () { that.$element.trigger('slid') }, 0) }).emulatetransitionend(this.transition_speed) } else { this.$element.trigger(e) if (e.isdefaultprevented()) return $active.removeclass('vc-active') $next.addclass('vc-active') this.sliding = false this.$slideline_inner.css(this.animation_position, this.current_pos_value + that.pos_units) } iscycling && this.cycle() if( this.current_index==0 && this.options.viewnum>0){ $next.removeclass('vc-active'); if(type=="next"){ this.$element.find('.vc-item:first').addclass("vc-active"); } } return this } carousel.prototype.setswipeanimationspeed = function() { this.$slideline_inner.addclass('vc-swipe-transition') } carousel.prototype.removeswipeanimationspeed = function() { this.$slideline_inner.removeclass('vc-swipe-transition') } /** * velocity * @param {number} delta_time * @param {number} delta_x * @param {number} delta_y * @returns {object} velocity */ carousel.prototype.velocity = function(time, x) { return { x: math.abs(x / time) || 0 } } carousel.prototype.recalculateslidelineheight = function(height, animate) { if(animate === true) { this.$slideline.animate({height: height}) } else { this.$slideline.height(height) } } /** * change layout size after resizing of window. */ carousel.prototype.resizeaction = function() { var max_height = 0, new_slideline_height = 0 if(this.options.mode === 'horizontal') { this.el_effect_size = this.$element.width() * ( this.options.partial ? this.partial_part : 1 ) this.$slideline.width(this.items_count*this.el_effect_size) } if (this.options.autoheight) { this.$items.height('auto') this.$items.each(function(){ var item_height = $(this).height() if(item_height > max_height) max_height = item_height }) this.$items.height(max_height) } else { this.recalculateslidelineheight(this.$active.height()) } if(this.options.mode === 'vertical') { this._step = this.$active.height() new_slideline_height = this.$active.height() * this.options.perview * (this.options.partial ? (1 + 1-this.partial_part) : 1) this.recalculateslidelineheight(new_slideline_height, false) this.$slideline_inner.css({top: -1 * this.$active.position().top}) this.el_effect_size = this._step } } carousel.prototype.returnswipedslide = function() { var params = {} params[this.animation_position] = this.current_pos_value + this.pos_units this.$slideline_inner.animate(params) } carousel.prototype._build = function() { //mobile don't build if($(window).width()<768 && this.$element.hasclass("vc-carousel vc-slide")){ return; } var el = this.$element.get(0), _touch_start_position = false, _touch_start_time = 0, _pos_before_touch = 0, _diff = 0, _moved = false, that = this, mode = this.options.mode this.getactiveindex() this.el_width = 0 this.items_count = this.$items.length this.$slideline = this.$element.find('.vc-carousel-slideline') this.slideline = this.$slideline.get(0) this.$slideline_inner = this.$slideline.find('> div') this.slideline_inner = this.$slideline_inner.get(0) this.partial_part = 0.8 this._slide_width = 0 this.swipe_velocity = 0.7 this.current_pos_value = 0 this.current_index = 0 // todo: default start position by options this.el_effect_size = 0 this.transition_speed = 600 this.$left_control = this.$element.find('.vc-left.vc-carousel-control') this.$right_control = this.$element.find('.vc-right.vc-carousel-control') // enable autoheight if partial if(this.options.partial) this.options.autoheight = true // add css classes for perview > 1 if(this.options.perview > 1) this.$element.addclass('vc-per-view-more vc-per-view-' + this.options.perview) if( mode === 'horizontal') { this.pos_units = '%' this._step = 100.00/this.items_count/this.options.perview this.animation_position = 'left' this.$items.width(this._step + this.pos_units) this.touch_direction = 'pagex' } else { this.pos_units = 'px' this.animation_position = 'top' this.touch_direction = 'pagey' } // hide first control if this.current_index === 0 if(this.options.hideonend) this.showhidecontrol() // add partial css class if partial if(this.options.partial) this.$element.addclass('vc_partial') // set indicator if(this.$indicators.length) { var $active_indecators = that.$indicators.children() .slice(this.current_index, this.current_index + this.options.perview) .addclass('vc-active') this.options.partial && $active_indecators.last().next().addclass('vc_partial') } $(window).resize(this.resizeaction.bind(this)); this.resizeaction() if(el.addeventlistener){ //ie 8 or lower el.addeventlistener("touchstart", function(e){ _touch_start_position = parsefloat(e[that.touch_direction]) _touch_start_time = e.timestamp _pos_before_touch = that.$slideline_inner.position()[that.animation_position] }.bind(this), false) el.addeventlistener('touchmove', function(e){ _diff = parsefloat(e[that.touch_direction]) - _touch_start_position _moved = math.abs(_diff) > 0 if(!_moved) return true e.preventdefault() that.slideline_inner.style[that.animation_position] = (_pos_before_touch + _diff) + 'px' }, false) el.addeventlistener('touchend', function(e){ var time,part,velocity if(_moved) { time= (e.timestamp-_touch_start_time)/1000 part = _diff/ that.el_effect_size velocity = that.velocity(time, part) if((velocity.x > that.swipe_velocity && part < 0) || part <= -0.7) { that.setswipeanimationspeed() that.next() } else if(velocity.x > that.swipe_velocity || part >= 0.7) { that.setswipeanimationspeed() that.prev() } else { that.returnswipedslide() } _moved = false } }, false) } this.$element.addclass('vc-build') return this } // carousel plugin definition // ========================== var old = $.fn.carousel $.fn.carousel = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('vc.carousel') var options = $.extend({}, carousel.defaults, $this.data(), typeof option == 'object' && option) var action = typeof option == 'string' ? option : options.slide if (!data) $this.data('vc.carousel', (data = new carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() else if (options.interval) data.pause().cycle() }) } $.fn.carousel.constructor = carousel // carousel no conflict // ==================== $.fn.carousel.noconflict = function () { $.fn.carousel = old return this } // carousel data-api // ================= $(document).off('click.vc.carousel.data-api').on('click.vc.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { var $this = $(this), href var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 var options = $.extend({}, $target.data(), $this.data()) var slideindex = $this.attr('data-slide-to') if (slideindex) options.interval = false $target.carousel(options) if (slideindex = $this.attr('data-slide-to')) { $target.data('vc.carousel').to(slideindex) } e.preventdefault() }) $(window).on('load', function () { $('[data-ride="vc-carousel"]').each(function () { var $carousel = $(this) $carousel.carousel($carousel.data()) }) }) })(window.jquery);