1/* global window, document, jQuery */ 2(function($) { 3 $.fn.flipster = function(options) { 4 var isMethodCall = typeof options === 'string' ? true : false; 5 6 if (isMethodCall) { 7 var method = options; 8 var args = Array.prototype.slice.call(arguments, 1); 9 } else { 10 var defaults = { 11 itemContainer: 'ul', // Container for the flippin' items. 12 itemSelector: 'li', // Selector for children of itemContainer to flip 13 style: 'coverflow', // Switch between 'coverflow' or 'carousel' display styles 14 start: 'center', // Starting item. Set to 0 to start at the first, 'center' to start in the middle or the index of the item you want to start with. 15 16 enableKeyboard: true, // Enable left/right arrow navigation 17 enableMousewheel: true, // Enable scrollwheel navigation (up = left, down = right) 18 enableTouch: true, // Enable swipe navigation for touch devices 19 20 onItemSwitch: $.noop, // Callback function when items are switched 21 disableRotation: false, 22 23 enableNav: false, // If true, flipster will insert an unordered list of the slides 24 navPosition: 'before', // [before|after] Changes the position of the navigation before or after the flipsterified items - case-insensitive 25 26 enableNavButtons: false, // If true, flipster will insert Previous / Next buttons 27 prevText: 'Previous', // Changes the text for the Previous button 28 nextText: 'Next' // Changes the text for the Next button 29 }; 30 var settings = $.extend({}, defaults, options); 31 32 var win = $(window); 33 } 34 35 return this.each(function(){ 36 37 var _flipster = $(this); 38 var methods; 39 40 if (isMethodCall) { 41 methods = _flipster.data('methods'); 42 return methods[method].apply(this, args); 43 } 44 45 var _flipItemsOuter; 46 var _flipItems; 47 var _flipNav; 48 var _flipNavItems; 49 var _current = 0; 50 51 var _startTouchX = 0; 52 var _actionThrottle = 0; 53 var _throttleTimeout; 54 var compatibility; 55 56 // public methods 57 methods = { 58 jump: jump 59 }; 60 _flipster.data('methods', methods); 61 62 function removeThrottle() { 63 _actionThrottle = 0; 64 } 65 66 function resize() { 67 _flipItemsOuter.height(calculateBiggestFlipItemHeight()); 68 _flipster.css("height","auto"); 69 if ( settings.style === 'carousel' ) { _flipItemsOuter.width(_flipItems.width()); } 70 } 71 72 function calculateBiggestFlipItemHeight() { 73 var biggestHeight = 0; 74 _flipItems.each(function() { 75 if ($(this).height() > biggestHeight) biggestHeight = $(this).height(); 76 }); 77 return biggestHeight; 78 } 79 80 function buildNav() { 81 if ( settings.enableNav && _flipItems.length > 1 ) { 82 var navCategories = [], 83 navItems = [], 84 navList = []; 85 86 _flipItems.each(function(){ 87 var category = $(this).data("flip-category"), 88 itemId = $(this).attr("id"), 89 itemTitle = $(this).attr("title"); 90 91 if ( typeof category !== 'undefined' ) { 92 if ( $.inArray(category,navCategories) < 0 ) { 93 navCategories.push(category); 94 navList[category] = '<li class="flip-nav-category"><a href="#" class="flip-nav-category-link" data-flip-category="'+category+'">'+category+'</a>\n<ul class="flip-nav-items">\n'; 95 } 96 } 97 98 if ( $.inArray(itemId,navItems) < 0 ) { 99 navItems.push(itemId); 100 var link = '<a href="#'+itemId+'" class="flip-nav-item-link">'+itemTitle+'</a></li>\n'; 101 if ( typeof category !== 'undefined' ) { 102 navList[category] = navList[category] + '<li class="flip-nav-item">' + link; 103 } 104 else { 105 navList[itemId] = '<li class="flip-nav-item no-category">' + link; 106 } 107 } 108 }); 109 110 var navDisplay = '<ul class="flipster-nav">\n'; 111 for (var catIndex in navCategories) { 112 navList[navCategories[catIndex]] = navList[navCategories[catIndex]] + "</ul>\n</li>\n"; 113 } 114 for (var navIndex in navList) { 115 navDisplay += navList[navIndex]; 116 } 117 navDisplay += '</ul>'; 118 119 if(settings.navPosition.toLowerCase() != "after") { 120 _flipNav = $(navDisplay).prependTo(_flipster); 121 } else { 122 _flipNav = $(navDisplay).appendTo(_flipster); 123 } 124 125 _flipNavItems = _flipNav.find("a").on("click",function(e){ 126 var target; 127 if ( $(this).hasClass("flip-nav-category-link") ) { 128 target = _flipItems.filter("[data-flip-category='"+$(this).data("flip-category")+"']"); 129 } else { 130 target = $(this.hash); 131 } 132 133 if ( target.length ) { 134 jump(target); 135 e.preventDefault(); 136 } 137 }); 138 } 139 } 140 141 function updateNav() { 142 if ( settings.enableNav && _flipItems.length > 1 ) {
143 var currentItem = $(_flipItems[_current]); 144 _flipNav.find(".flip-nav-current").removeClass("flip-nav-current"); 145 _flipNavItems.filter("[href='#"+currentItem.attr("id")+"']").addClass("flip-nav-current"); 146 _flipNavItems.filter("[data-flip-category='"+currentItem.data("flip-category")+"']").parent().addClass("flip-nav-current"); 147 } 148 } 149 150 function buildNavButtons() { 151 if ( settings.enableNavButtons && _flipItems.length > 1 ) { 152 _flipster.find(".flipto-prev, .flipto-next").remove(); 153 _flipster.append("<a href='#' class='flipto-prev'>"+settings.prevText+"</a> <a href='#' class='flipto-next'>"+settings.nextText+"</a>"); 154 155 _flipster.children('.flipto-prev').on("click", function(e) { 156 jump("left"); 157 e.preventDefault(); 158 }); 159 160 _flipster.children('.flipto-next').on("click", function(e) { 161 jump("right"); 162 e.preventDefault(); 163 }); 164 } 165 } 166 167 function center() { 168 var currentItem = $(_flipItems[_current]).addClass("flip-current"); 169 170 _flipItems.removeClass("flip-prev flip-next flip-current flip-past flip-future no-transition"); 171 172 if ( settings.style === 'carousel' ) { 173 174 _flipItems.addClass("flip-hidden"); 175 176 var nextItem = $(_flipItems[_current+1]), 177 futureItem = $(_flipItems[_current+2]), 178 prevItem = $(_flipItems[_current-1]), 179 pastItem = $(_flipItems[_current-2]); 180 181 if ( _current === 0 ) { 182 prevItem = _flipItems.last(); 183 pastItem = prevItem.prev(); 184 } 185 else if ( _current === 1 ) { 186 pastItem = _flipItems.last(); 187 } 188 else if ( _current === _flipItems.length-2 ) { 189 futureItem = _flipItems.first(); 190 } 191 else if ( _current === _flipItems.length-1 ) { 192 nextItem = _flipItems.first(); 193 futureItem = $(_flipItems[1]); 194 } 195 196 futureItem.removeClass("flip-hidden").addClass("flip-future"); 197 pastItem.removeClass("flip-hidden").addClass("flip-past"); 198 nextItem.removeClass("flip-hidden").addClass("flip-next"); 199 prevItem.removeClass("flip-hidden").addClass("flip-prev"); 200 201 } 202 else { 203 var spacer = currentItem.outerWidth()/2; 204 var totalLeft = 0; 205 var totalWidth = _flipItemsOuter.width(); 206 var currentWidth = currentItem.outerWidth(); 207 var currentLeft = (_flipItems.index(currentItem)*currentWidth)/2 +spacer/2; 208 209 _flipItems.removeClass("flip-hidden"); 210 211 for (var i = 0; i < _flipItems.length; i++) { 212 var thisItem = $(_flipItems[i]); 213 var thisWidth = thisItem.outerWidth(); 214 215 if (i < _current) { 216 thisItem.addClass("flip-past") 217 .css({ 218 "z-index" : i, 219 "left" : (i*thisWidth/2)+"px" 220 }); 221 } 222 else if ( i > _current ) { 223 thisItem.addClass("flip-future") 224 .css({ 225 "z-index" : _flipItems.length-i, 226 "left" : (i*thisWidth/2)+spacer+"px" 227 }); 228 } 229 } 230 231 currentItem.css({ 232 "z-index" : _flipItems.length+1, 233 "left" : currentLeft +"px" 234 }); 235 236 totalLeft = (currentLeft + (currentWidth/2)) - (totalWidth/2); 237 var newLeftPos = -1*(totalLeft)+"px"; 238 /* Untested Compatibility */ 239 if (compatibility) { 240 var leftItems = $(".flip-past"); 241 var rightItems = $(".flip-future"); 242 $(".flip-current").css("zoom", "1.0"); 243 for (i = 0; i < leftItems.length; i++) { 244 $(leftItems[i]).css("zoom", (100-((leftItems.length-i)*5)+"%")); 245 } 246 for (i = 0; i < rightItems.length; i++) { 247 $(rightItems[i]).css("zoom", (100-((i+1)*5)+"%")); 248 } 249 250 _flipItemsOuter.animate({"left":newLeftPos}, 333); 251 } 252 else { 253 _flipItemsOuter.css("left", newLeftPos); 254 } 255 } 256 257 currentItem 258 .addClass("flip-current") 259 .removeClass("flip-prev flip-next flip-past flip-future flip-hidden"); 260 261 resize(); 262 updateNav(); 263 264 currentItem.trigger('flip.show', _current); 265 settings.onItemSwitch.call(_flipster); 266 } 267 268 function jump(to) { 269 $(_flipItems[_current]).trigger('flip.hide', _current); 270 if ( _flipItems.length > 1 ) { 271 if ( to === "left" ) {
272 if ( _current > 0 ) { _current--; } 273 else { _current = _flipItems.length-1; } 274 } 275 else if ( to === "right" ) { 276 if ( _current < _flipItems.length-1 ) { _current++; } 277 else { _current = 0; } 278 } else if ( typeof to === 'number' ) { 279 _current = to; 280 } else { 281 // if object is sent, get its index 282 _current = _flipItems.index(to); 283 } 284 285 center(); 286 } 287 } 288 289 function init() { 290 // Basic setup 291 _flipster.addClass("flipster flipster-active flipster-"+settings.style).css("visibility","hidden"); 292 if (settings.disableRotation) 293 _flipster.addClass('no-rotate'); 294 _flipItemsOuter = _flipster.find(settings.itemContainer).addClass("flip-items"); 295 _flipItems = _flipItemsOuter.find(settings.itemSelector).addClass("flip-item flip-hidden").wrapInner("<div class='flip-content' />"); 296 297 //Browsers that don't support CSS3 transforms get compatibility: 298 var isIEmax8 = ('\v' === 'v'); //IE <= 8 299 var checkIE = document.createElement("b"); 300 checkIE.innerHTML = "<!--[if IE 9]><i></i><![endif]-->"; //IE 9 301 var isIE9 = checkIE.getElementsByTagName("i").length === 1; 302 if (isIEmax8 || isIE9) { 303 compatibility = true; 304 _flipItemsOuter.addClass("compatibility"); 305 } 306 307 // Insert navigation if enabled. 308 buildNav(); 309 buildNavButtons(); 310 311 // Set the starting item 312 if (settings.start && _flipItems.length > 1) { 313 // Find the middle item if start = center 314 if ( settings.start === 'center' ) { 315 if (!_flipItems.length % 2) { 316 _current = _flipItems.length/2 + 1; 317 } else { 318 _current = Math.floor(_flipItems.length/2); 319 } 320 } else { 321 _current = settings.start; 322 } 323 } 324 325 326 // initialize containers 327 resize(); 328 329 // Necessary to start flipster invisible and then fadeIn so height/width can be set accurately after page load 330 _flipster.hide().css("visibility","visible").fadeIn(400,function(){ center(); }); 331 332 // Attach event bindings. 333 win.on("resize.flipster", function() { 334 resize(); 335 center(); 336 }); 337 338 // Navigate directly to an item by clicking 339 _flipItems.on("click", function(e) { 340 if ( !$(this).hasClass("flip-current") ) { e.preventDefault(); } 341 jump(_flipItems.index(this)); 342 }); 343 344 // Keyboard Navigation 345 if (settings.enableKeyboard && _flipItems.length > 1) { 346 win.on("keydown.flipster", function(e) { 347 _actionThrottle++; 348 if (_actionThrottle % 7 !== 0 && _actionThrottle !== 1) return; //if holding the key down, ignore most events 349 350 var code = e.which; 351 if (code === 37 ) { 352 e.preventDefault(); 353 jump('left'); 354 } else if (code === 39 ) { 355 e.preventDefault(); 356 jump('right'); 357 } 358 }); 359 360 win.on("keyup.flipster", function(e){ 361 _actionThrottle = 0; //reset action throttle on key lift to avoid throttling new interactions 362 }); 363 } 364 365 // Mousewheel Navigation 366 if (settings.enableMousewheel && _flipItems.length > 1) { // TODO: Fix scrollwheel on Firefox 367 _flipster.on("mousewheel.flipster", function(e){ 368 _throttleTimeout = window.setTimeout(removeThrottle, 500); //throttling should expire if scrolling pauses for a moment. 369 _actionThrottle++; 370 if (_actionThrottle % 4 !==0 && _actionThrottle !== 1) return; //throttling like with held-down keys 371 window.clearTimeout(_throttleTimeout); 372 373 if ( e.originalEvent.wheelDelta /120 > 0 ) { jump("left"); } 374 else { jump("right"); } 375 376 e.preventDefault(); 377 }); 378 } 379 380 // Touch Navigation 381 if ( settings.enableTouch && _flipItems.length > 1 ) { 382 _flipster.on("touchstart.flipster", function(e) { 383 _startTouchX = e.originalEvent.targetTouches[0].screenX; 384 }); 385 386 _flipster.on("touchmove.flipster", function(e) { 387 e.preventDefault(); 388 var nowX = e.originalEvent.targetTouches[0].screenX; 389 var touchDiff = nowX-_startTouchX; 390 if (touchDiff > _flipItems[0].clientWidth/1.75){ 391 jump("left"); 392 _startTouchX = nowX; 393 }else if (touchDiff < -1*(_flipItems[0].clientWidth/1.75)){ 394 jump("right"); 395 _startTouchX = nowX; 396 } 397 }); 398 399 _flipster.on("touchend.flipster", function(e) { 400 _startTouchX = 0; 401 }); 402 } 403 } 404 405 // Initialize if flipster is not already active. 406 if ( !_flipster.hasClass("flipster-active") ) { init(); } 407 }); 408 }; 409})(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.