1/** 2 * Carousello 3 * 4 * @version 1.0 5 * 6 * Copyright 2013, UpSolution 7 */ 8 9(function($) { 10 "use strict"; 11 12 var Carousello = function(container, options) 13 { 14 // Context 15 var that = this; 16 this.container = $(container); 17 // Apply options 18 options = $.extend({}, $.fn.carousello.defaults, typeof options === 'object' && options); 19 this.options = options; 20 // Grab the actual widget name (as carousello can be applied to different widgets) 21 this.widgetName = this.container.attr('class').split(' ')[0]; 22 // Grab dom elements 23 this.btnPrev = this.container.find('.'+this.widgetName+'-nav.to_prev'); 24 this.btnNext = this.container.find('.'+this.widgetName+'-nav.to_next'); 25 this.list = this.container.find('.'+this.widgetName+'-list'); 26 this.listH = this.container.find('.'+this.widgetName+'-list-h'); 27 this.items = this.container.find('.'+this.widgetName+'-item'); 28 // Count dimensions 29 this.count = this.items.length; 30 this.itemWidth = $(this.items).outerWidth(); 31 this.itemOffset = parseInt($(this.items).css('margin-right'), 10); 32 // 3D Effect 33 if (this.options.use3d){ 34 this.cssPrefix = this._get3DPrefix(); 35 if (this.cssPrefix === false) { 36 this.options.use3d = false; 37 } 38 } 39 // Current position 40 this.position = 0; 41 // Events 42 this.btnPrev.click(function(){ that.slidePrev(); }); 43 this.btnNext.click(function(){ that.slideNext(); }); 44 // Make responsive 45 $(window).resize(function(){ 46 clearTimeout(that._resizeTimer); 47 that._resizeTimer = setTimeout(function(){that.handleResize();}, that.options.resizeDelay); 48 }); 49 if (this.options.use3d){ 50 // Requires imagesloaded plugin 51 // http://github.com/desandro/imagesloaded 52 this.container.imagesLoaded(function(){ 53 that.list.height(that.items.outerHeight()); 54 that.handleResize(); 55 }); 56 }else{ 57 this.handleResize(); 58 } 59 }; 60 61 Carousello.prototype = { 62 63 /** 64 * Obtain browser css3 prefix or false if 3d transforms are not supported 65 * Based on modernizer 66 * @link http://modernizr.com 67 * @private 68 * @return {String} Prefix or false 69 */ 70 _get3DPrefix: function() { 71 var div = document.createElement('div'), 72 ret = false, 73 properties = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective'], 74 prefixes = ['', '-o-', '-moz-', '-webkit-']; 75 for (var i = properties.length - 1; i >= 0; i--) { 76 ret = ret ? ret : div.style[properties[i]] !== undefined; 77 } 78 if (ret){ 79 var st = document.createElement('style'); 80 // webkit allows this media query to succeed only if the feature is enabled. 81 // "@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){#modernizr{height:3px}}" 82 document.getElementsByTagName('head')[0].appendChild(st); 83 div.id = 'test3d'; 84 document.body.appendChild(div); 85 for (var j = 0; j < prefixes.length; j++){ 86 st.textContent = '@media ('+prefixes[j]+'transform-3d){#test3d{height:3px}}'; 87 if (div.offsetHeight === 3){ 88 ret = prefixes[j]; 89 break; 90 } 91 } 92 st.parentNode.removeChild(st); 93 div.parentNode.removeChild(div); 94 } 95 if (ret === true) { 96 if (div.style.MozPerspective !== undefined) { 97 ret = '-moz-'; 98 } else 99 if (div.style.WebkitPerspective !== undefined) { 100 ret = '-webkit-'; 101 } else { 102 ret = ''; 103 } 104 } 105 return ret; 106 }, 107 108 slidePrev: function() 109 { 110 var newPosition = Math.max(0, this.position - this.perRow); 111 this.slideTo(newPosition); 112 }, 113 114 slideNext: function() 115 { 116 var newPosition = Math.min(this.count - this.perRow, this.position + this.perRow); 117 if (this.options.use3d) { 118 newPosition = this.position + this.perRow; 119 } 120 this.slideTo(newPosition); 121 }, 122 123 slideTo: function(position) 124 { 125 if (position === this.position) { 126 return; 127 } 128 if (this.options.use3d){ 129 // 3D transition 130 var showGroup = Math.min(Math.floor(position / this.perRow), this.groups.length-1), 131 that = this; 132 position = showGroup * this.perRow; 133 this.listH.animate({ 134 angle: -1 * this.baseAngle * showGroup 135 }, { 136 duration: this.options.duration, 137 easing: this.options.easing, 138 step: function(angle){ 139 angle = parseInt(angle * 100, 10) / 100; 140 that.listH.css(that.cssPrefix+'transform', 'translateZ(-'+that.translateZ+'px) rotateY('+angle+'deg)'); 141 }, 142 queue: false 143 }); 144 }else{ 145 // 2D transition 146 this.listH.animate({ 147 left: -1*position*(this.itemWidth+this.itemOffset) 148 }, { 149 duration: this.options.duration, 150 easing: this.options.easing, 151 queue: false 152 }); 153 } 154 this.btnPrev[(position === 0)?'addClass':'removeClass']('disabled'); 155 this.btnNext[(position >= (this.count - this.perRow))?'addClass':'removeClass']('disabled'); 156 this.position = position; 157 }, 158 159 handleResize: function() 160 { 161 var containerWidth = this.container.width(), 162 oldPerRow = this.perRow, 163 that = this; 164 this.perRow = Math.max(1, Math.floor((containerWidth + this.itemOffset) / (this.itemWidth + this.itemOffset))); 165 var listWidth = this.perRow * (this.itemWidth + this.itemOffset) - this.itemOffset; 166 this.list.width(listWidth);
167 if (this.options.use3d && (oldPerRow === undefined || this.perRow !== oldPerRow)){ 168 // Separate items into groups for 3d effect 169 this.listH.append(this.items); 170 this.listH.children('.'+this.widgetName+'-itemgroup').remove(); 171 for (var i = 0, l = Math.ceil(this.count / this.perRow); i < l; i++){ 172 var group = $('<div/>', {'class': this.widgetName+'-itemgroup'}).appendTo(this.listH); 173 for (var j = 0; j < this.perRow; j++){ 174 if (this.items[i*this.perRow + j] === undefined) { 175 break; 176 } 177 group.append(this.items[i*this.perRow + j]); 178 } 179 } 180 this.groups = this.container.find('.'+this.widgetName+'-itemgroup'); 181 this.baseAngle = Math.min(120, 360 / this.groups.length); 182 this.translateZ = Math.round( 0.5 * listWidth / Math.tan(Math.PI / Math.max(3, this.groups.length))); 183 this.list 184 .css({position: 'relative', 'overflow': (this.groups.length < 5) ? 'visible' : 'hidden'}) 185 .css(this.cssPrefix+'perspective', '800px'); 186 this.listH 187 .css({position: 'absolute', height: '100%', width: '100%'}) 188 .css(this.cssPrefix+'transform', 'rotateY(0deg) translateZ(-'+this.translateZ+'px)') 189 .css(this.cssPrefix+'transform-style', 'preserve-3d') 190 .css(this.cssPrefix+'perspective-origin', '50% 100px'); 191 this.list.height(this.items.outerHeight()); 192 this.groups.css({position: 'absolute', left: 0, width: '100%', height: '100%'}); 193 $.each(this.groups, function(k, group){ 194 $(group).css(that.cssPrefix+'transform', 'rotateY('+(that.baseAngle*k)+'deg) translateZ('+that.translateZ+'px)'); 195 }); 196 } 197 if (oldPerRow !== undefined && this.perRow !== oldPerRow){ 198 if (this.position > this.count - this.perRow) { 199 this.slideTo(this.count - this.perRow); 200 } 201 this.btnNext[(this.position >= (this.count - this.perRow))?'addClass':'removeClass']('disabled'); 202 } 203 // Hide arrows if there are too few items 204 if (this.perRow >= this.count) { 205 this.btnPrev.hide(); 206 this.btnNext.hide(); 207 } else { 208 this.btnPrev.show(); 209 this.btnNext.show(); 210 } 211 } 212 213 }; 214 215 /** 216 * Easings 217 * Original functions by George McGinley Smith 218 * @link http://gsgd.co.uk/sandbox/jquery/easing/ 219 */ 220 if ($.easing.easeOutBack === undefined) { 221 $.easing.easeOutBack = function (x, t, b, c, d, s){ 222 if (s === undefined) { 223 s = 1.70158; 224 } 225 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 226 }; 227 } 228 if ($.easing.easeInOutExpo === undefined) { 229 $.easing.easeInOutExpo = function(e, t, n, r, i){ 230 if (t === 0) { 231 return n; 232 } 233 if (t === i) { 234 return n+r; 235 } 236 if ((t /= i/2) < 1) { 237 return r/2*Math.pow(2,10*(t-1))+n; 238 } 239 return r/2*(-Math.pow(2,-10*--t) + 2) + n; 240 }; 241 } 242 243 $.fn.carousello = function(options){ 244 return this.each(function(){ 245 var $this = $(this), 246 data = $this.data('carousello'); 247 if ( ! data) { 248 $this.data('carousello', (data = new Carousello(this, options))); 249 } 250 }); 251 }; 252 253 $.fn.carousello.defaults = { 254 255 /** 256 * @var {Boolean} Try to use 3D if possible 257 */ 258 use3d: true, 259 260 /** 261 * @var {Number} Animation duration 262 */ 263 duration: 500, 264 265 /** 266 * @var {Function} Default animation easing 267 */ 268 easing: 'easeInOutExpo', 269 270 /** 271 * @var {Number} Resize delay to reduce resize event calls 272 */ 273 resizeDelay: 50 274 }; 275 276 $.fn.carousello.Constructor = Carousello; 277 278 279})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.