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 enableNav: false, // If true, flipster will insert an unordered list of the slides 21 enableNavButtons: false, // If true, flipster will insert Previous / Next buttons 22 23 onItemSwitch: $.noop, // Callback function when items are switches 24 disableRotation: false, 25 26 navPosition: 'before', // [before|after] Changes the position of the navigation before or after the flipsterified items - case-insensitive 27 28 prevText: 'Previous', // Changes the text for the Previous button 29 nextText: 'next' // Changes the text for the Next button 30 }; 31 var settings = $.extend({}, defaults, options); 32 33 var win = $(window); 34 } 35 36 return this.each(function () { 37 38 var _flipster = $(this); 39 var methods; 40 41 if (isMethodCall) { 42 methods = _flipster.data('methods'); 43 return methods[method].apply(this, args); 44 } 45 46 var _flipItemsOuter; 47 var _flipItems; 48 var _flipNav; 49 var _flipNavItems; 50 var _current = 0; 51 52 var _startTouchX = 0; 53 var _actionThrottle = 0; 54 var _throttleTimeout; 55 var compatibility; 56 57 // public methods 58 methods = { 59 jump: jump 60 }; 61 _flipster.data('methods', methods); 62 63 function removeThrottle() { 64 _actionThrottle = 0; 65 } 66 67 function resize() { 68 _flipItemsOuter.height(calculateBiggestFlipItemHeight()); 69 _flipster.css("height", "auto"); 70 if (settings.style === 'carousel') { 71 _flipItemsOuter.width(_flipItems.width()); 72 } 73 } 74 75 function calculateBiggestFlipItemHeight() { 76 var biggestHeight = 0; 77 _flipItems.each(function () { 78 if ($(this).height() > biggestHeight) 79 biggestHeight = $(this).height(); 80 }); 81 return biggestHeight; 82 } 83 84 function buildNav() { 85 if (settings.enableNav && _flipItems.length > 1) { 86 var navCategories = [], 87 navItems = [], 88 navList = []; 89 90 _flipItems.each(function () { 91 var category = $(this).data("flip-category"), 92 itemId = $(this).attr("id"), 93 itemTitle = $(this).attr("title"); 94 95 if (typeof category !== 'undefined') { 96 if ($.inArray(category, navCategories) < 0) { 97 navCategories.push(category); 98 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'; 99 } 100 } 101 102 if ($.inArray(itemId, navItems) < 0) { 103 navItems.push(itemId); 104 var link = '<a href="#' + itemId + '" class="flip-nav-item-link">' + itemTitle + '</a></li>\n'; 105 if (typeof category !== 'undefined') { 106 navList[category] = navList[category] + '<li class="flip-nav-item">' + link; 107 } else { 108 navList[itemId] = '<li class="flip-nav-item no-category">' + link; 109 } 110 } 111 }); 112 113 var navDisplay = '<ul class="flipster-nav">\n'; 114 for (var catIndex in navCategories) { 115 navList[navCategories[catIndex]] = navList[navCategories[catIndex]] + "</ul>\n</li>\n"; 116 } 117 for (var navIndex in navList) { 118 navDisplay += navList[navIndex]; 119 } 120 navDisplay += '</ul>'; 121 122 if (settings.navPosition.toLowerCase() != "after") { 123 _flipNav = $(navDisplay).prependTo(_flipster); 124 } else { 125 _flipNav = $(navDisplay).appendTo(_flipster); 126 } 127 128 _flipNavItems = _flipNav.find("a").on("click", function (e) { 129 var target; 130 if ($(this).hasClass("flip-nav-category-link")) { 131 target = _flipItems.filter("[data-flip-category='" + $(this).data("flip-category") + "']"); 132 } else { 133 target = $(this.hash); 134 } 135 136 if (target.length) { 137 jump(target); 138 e.preventDefault(); 139 } 140 }); 141 } 142 } 143 144 function updateNav() { 145 if (settings.enableNav && _flipItems.length > 1) {
146 var currentItem = $(_flipItems[_current]); 147 _flipNav.find(".flip-nav-current").removeClass("flip-nav-current"); 148 _flipNavItems.filter("[href='#" + currentItem.attr("id") + "']").addClass("flip-nav-current"); 149 _flipNavItems.filter("[data-flip-category='" + currentItem.data("flip-category") + "']").parent().addClass("flip-nav-current"); 150 } 151 } 152 153 function buildNavButtons() { 154 if (settings.enableNavButtons && _flipItems.length > 1) { 155 _flipster.find(".flipto-prev, .flipto-next").remove(); 156 _flipster.append("<div class='flipto-nav'><a href='#' class='flipto-prev'>" + settings.prevText + "</a> <a href='#' class='flipto-next'>" + settings.nextText + "</a></div>"); 157 158 _flipster.find('.flipto-prev').on("click", function (e) { 159 jump("left"); 160 e.preventDefault(); 161 }); 162 163 _flipster.find('.flipto-next').on("click", function (e) { 164 jump("right"); 165 e.preventDefault(); 166 }); 167 } 168 } 169 170 function center() { 171 var currentItem = $(_flipItems[_current]).addClass("flip-current"); 172 173 _flipItems.removeClass("flip-prev flip-next flip-current flip-past flip-future no-transition"); 174 175 if (settings.style === 'carousel') { 176 177 _flipItems.addClass("flip-hidden"); 178 179 var nextItem = $(_flipItems[_current + 1]), 180 futureItem = $(_flipItems[_current + 2]), 181 prevItem = $(_flipItems[_current - 1]), 182 pastItem = $(_flipItems[_current - 2]); 183 184 if (_current === 0) { 185 prevItem = _flipItems.last(); 186 pastItem = prevItem.prev(); 187 } else if (_current === 1) { 188 pastItem = _flipItems.last(); 189 } else if (_current === _flipItems.length - 2) { 190 futureItem = _flipItems.first(); 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 } else { 202 var spacer = currentItem.outerWidth() / 2; 203 var totalLeft = 0; 204 var totalWidth = _flipItemsOuter.width(); 205 var currentWidth = currentItem.outerWidth(); 206 var currentLeft = (_flipItems.index(currentItem) * currentWidth) / 2 + spacer / 2; 207 208 _flipItems.removeClass("flip-hidden"); 209 210 for (var i = 0; i < _flipItems.length; i++) { 211 var thisItem = $(_flipItems[i]); 212 var thisWidth = thisItem.outerWidth(); 213 214 if (i < _current) { 215 thisItem.addClass("flip-past") 216 .css({ 217 "z-index": i, 218 "left": (i * thisWidth / 2) + "px" 219 }); 220 } else if (i > _current) { 221 thisItem.addClass("flip-future") 222 .css({ 223 "z-index": _flipItems.length - i, 224 "left": (i * thisWidth / 2) + spacer + "px" 225 }); 226 } 227 } 228 229 currentItem.css({ 230 "z-index": _flipItems.length + 1, 231 "left": currentLeft + "px" 232 }); 233 234 totalLeft = (currentLeft + (currentWidth / 2)) - (totalWidth / 2); 235 var newLeftPos = -1 * (totalLeft) + "px"; 236 /* Untested Compatibility */ 237 if (compatibility) { 238 var leftItems = $(".flip-past"); 239 var rightItems = $(".flip-future"); 240 $(".flip-current").css("zoom", "1.0"); 241 for (i = 0; i < leftItems.length; i++) { 242 $(leftItems[i]).css("zoom", (100 - ((leftItems.length - i) * 5) + "%")); 243 } 244 for (i = 0; i < rightItems.length; i++) { 245 $(rightItems[i]).css("zoom", (100 - ((i + 1) * 5) + "%")); 246 } 247 248 _flipItemsOuter.animate({ 249 "left": newLeftPos 250 }, 333); 251 } else { 252 _flipItemsOuter.css("left", newLeftPos); 253 } 254 } 255 256 currentItem 257 .addClass("flip-current") 258 .removeClass("flip-prev flip-next flip-past flip-future flip-hidden"); 259 260 resize(); 261 updateNav(); 262 settings.onItemSwitch.call(this); 263 } 264 265 function jump(to) { 266 if (_flipItems.length > 1) { 267 if (to === "left") { 268 if (_current > 0) { 269 _current--; 270 } else { 271 _current = _flipItems.length - 1; 272 } 273 } else if (to === "right") { 274 if (_current < _flipItems.length - 1) { 275 _current++; 276 } else { 277 _current = 0; 278 } 279 } else if (typeof to === 'number') { 280 _current = to; 281 } else { 282 // if object is sent, get its index 283 _current = _flipItems.index(to); 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 () { 331 center(); 332 }); 333 334 // Attach event bindings. 335 win.resize(function () { 336 resize(); 337 center(); 338 }); 339 340 // Navigate directly to an item by clicking 341 _flipItems.on("click", function (e) { 342 if (!$(this).hasClass("flip-current")) { 343 e.preventDefault(); 344 } 345 jump(_flipItems.index(this)); 346 }); 347 348 // Keyboard Navigation 349 if (settings.enableKeyboard && _flipItems.length > 1) { 350 win.on("keydown.flipster", function (e) { 351 _actionThrottle++; 352 if (_actionThrottle % 7 !== 0 && _actionThrottle !== 1) 353 return; //if holding the key down, ignore most events 354 355 var code = e.which; 356 if (code === 37) { 357 e.preventDefault(); 358 jump('left'); 359 } else if (code === 39) { 360 e.preventDefault(); 361 jump('right'); 362 } 363 }); 364 365 win.on("keyup.flipster", function (e) { 366 _actionThrottle = 0; //reset action throttle on key lift to avoid throttling new interactions 367 }); 368 } 369 370 // Mousewheel Navigation 371 if (settings.enableMousewheel && _flipItems.length > 1) { // TODO: Fix scrollwheel on Firefox 372 _flipster.on("mousewheel.flipster", function (e) { 373 _throttleTimeout = window.setTimeout(removeThrottle, 500); //throttling should expire if scrolling pauses for a moment. 374 _actionThrottle++; 375 if (_actionThrottle % 4 !== 0 && _actionThrottle !== 1) 376 return; //throttling like with held-down keys 377 window.clearTimeout(_throttleTimeout); 378 379 if (e.originalEvent.wheelDelta / 120 > 0) { 380 jump("left"); 381 } else { 382 jump("right"); 383 } 384 385 e.preventDefault(); 386 }); 387 } 388 389 // Touch Navigation 390 if (settings.enableTouch && _flipItems.length > 1) { 391 _flipster.on("touchstart.flipster", function (e) { 392 _startTouchX = e.originalEvent.targetTouches[0].screenX; 393 }); 394 395 _flipster.on("touchmove.flipster", function (e) { 396 e.preventDefault(); 397 var nowX = e.originalEvent.targetTouches[0].screenX; 398 var touchDiff = nowX - _startTouchX; 399 if (touchDiff > _flipItems[0].clientWidth / 1.75) { 400 jump("left"); 401 _startTouchX = nowX; 402 }
402 else if (touchDiff < -1 * (_flipItems[0].clientWidth / 1.75)) { 403 jump("right"); 404 _startTouchX = nowX; 405 } 406 }); 407 408 _flipster.on("touchend.flipster", function (e) { 409 _startTouchX = 0; 410 }); 411 } 412 } 413 414 // Initialize if flipster is not already active. 415 if (!_flipster.hasClass("flipster-active")) { 416 init(); 417 } 418 }); 419 }; 420})(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.