1/* 2 =========================================================== 3 4 Note: SlidesJS version 2.0 beta 1 is not meant 5 for production deployment. Please download the latest 6 version at https://github.com/nathansearles/Slides. 7 8 =========================================================== 9*/ 10 11/* 12 13 .d8888b. 888 d8b 888 888888 .d8888b. 14 d88P Y88b 888 Y8P 888 "88b d88P Y88b 15 Y88b. 888 888 888 Y88b. 16 "Y888b. 888 888 .d88888 .d88b. .d8888b 888 "Y888b. 17 "Y88b. 888 888 d88" 888 d8P Y8b 88K 888 "Y88b. 18 "888 888 888 888 888 88888888 "Y8888b. 888 "888 19 Y88b d88P 888 888 Y88b 888 Y8b. X88 88P Y88b d88P 20 "Y8888P" 888 888 "Y88888 "Y8888 88888P' 888 "Y8888P" 21 .d88P 22 .d88P" 23 888P" 24 25 Created by Nathan Searles <http://nathansearles.com> 26 27 Documentation and examples <http://slidesjs.com> 28 Support forum <http://groups.google.com/group/slidesjs> 29 30 Version: 2.0 beta 1 31 Updated: June 22nd, 2011 32 33 SlidesJS is an open source project, contribute at GitHub: 34 https://github.com/nathansearles/Slides 35 36 (c) 2011 by Nathan Searles 37 38 Thanks to: 39 Thomas Reynolds <http://awardwinningfjords.com/> 40 Adam j. Sontag <http://ajpiano.com/> 41 42 Licensed under the Apache License, Version 2.0 (the "License"); 43 you may not use this file except in compliance with the License. 44 You may obtain a copy of the License at 45 46 http://www.apache.org/licenses/LICENSE-2.0 47 48 Unless required by applicable law or agreed to in writing, software 49 distributed under the License is distributed on an "AS IS" BASIS, 50 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 51 See the License for the specific language governing permissions and 52 limitations under the License. 53*/ 54 55/* 56 Documentaion 57 ============================================================ 58 59 Basic Markup Structure 60 ============================================================ 61 62 For just images you can simply use: 63 64 <div id="slides"> 65 <img src="http://slidesjs.com/examples/standard/img/slide-1.jpg" width="570" height="270" alt="Slide 1"> 66 <img src="http://slidesjs.com/examples/standard/img/slide-2.jpg" width="570" height="270" alt="Slide 2"> 67 <img src="http://slidesjs.com/examples/standard/img/slide-3.jpg" width="570" height="270" alt="Slide 3"> 68 <img src="http://slidesjs.com/examples/standard/img/slide-4.jpg" width="570" height="270" alt="Slide 4"> 69 </div> 70 71 Or you can use <div>s for your slides 72 73 <div id="slides"> 74 <div> 75 <img src="http://slidesjs.com/examples/standard/img/slide-1.jpg" width="570" height="270" alt="Slide 1"> 76 </div> 77 <div> 78 <img src="http://slidesjs.com/examples/standard/img/slide-2.jpg" width="570" height="270" alt="Slide 2"> 79 </div> 80 <div> 81 <img src="http://slidesjs.com/examples/standard/img/slide-3.jpg" width="570" height="270" alt="Slide 3"> 82 </div> 83 <div> 84 <img src="http://slidesjs.com/examples/standard/img/slide-4.jpg" width="570" height="270" alt="Slide 4"> 85 </div> 86 </div> 87 88 Simple as that. No extra <div>s, no navigation or pagination to define, it's all created for you. SlidesJS creates 89 two <div>s for the slideshow, ".slidesContainer" and ".slidesControl", both are required and can not be changed. 90 91 Navigation classes are ".slidesPrevious" and ".slidesNext" and are created as anchor tags. These cannot be changed. 92 93 Pagination uses an unordered list markup structure. The <ul> has a class of ".slidesPagination". This cannot be changed. 94 95 You may define your own navigation or pagination, but they must use the same class names, 96 sorry it saves from including extraneous code. 97 98 Basic CSS 99 ============================================================ 100 101 No CSS required. Shit yeah! 102 103 Initialize SlidesJS 104 ============================================================ 105 106 <script> 107 $(function(){ 108 $("#slides").slides(); 109 }); 110 </script> 111 112 Tip: With SidesJS 2 you need to define the width and height if it's different from the default (780px x 300px). This resolves many issues having to do with loading and makes SlidesJS 2 self contained, not requiring any CSS. 113 114 <pre><script> 115 $(function(){ 116 $("#slides").slides({ 117 width: 640, 118 height: 480 119 }); 120 }); 121 </script></pre> 122 123 Method Calls - The good stuff 124 ============================================================ 125 126 Play: 127 $("#slides").slides("play"); 128 129 Pause: 130 $("#slides").slides("pause"); 131 132 Stop: 133 $("#slides").slides("stop"); 134 135 Next: 136 $("#slides").slides("next"); 137 - Uses default effect
138 139 $("#slides").slides("next","fade"); 140 - Define effect, "slide" or "fade" 141 142 Previous: 143 $("#slides").slides("previous"); 144 - Uses default effect 145 146 $("#slides").slides("previous","fade"); 147 - Define effect, "slide" or "fade" 148 149 Goto a slide 150 $("#slides").slides("slide",2); 151 - Goto slide 2 using default effect 152 153 $("#slides").slides("slide",4,"fade"); 154 - Define effect, "slide" or "fade" 155 156 Update: 157 $("#slides").slides("update"); 158 - Rebuilds pagination 159 160 Destroy: 161 $("#slides").slides("destroy"); 162 - Removes SlidesJS, returns to predefined state 163 164 Status: 165 $("#slides").slides("status"); 166 - Returns JSON object: 167 { 168 current: 4, 169 state: "playing", 170 total: 7 171 } 172 173 $("#slides").slides("status","current"); 174 - Returns current slide number 175 176 $("#slides").slides("status","state"); 177 - Returns playing, paused, or stopped 178 179 $("#slides").slides("status","total"); 180 - Returns total slides in slideshow 181 182 Options 183 ============================================================ 184 Check out the notes on the options below 185*/ 186 187/* 188 jQuery UI Widget, skip past this for SlidesJS 189*/ 190 191/*! 192 * jQuery UI Widget @VERSION 193 * 194 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 195 * Dual licensed under the MIT or GPL Version 2 licenses. 196 * http://jquery.org/license 197 * 198 * http://docs.jquery.com/UI/Widget 199 */ 200(function ($, undefined) { 201 var slice = Array.prototype.slice; 202 var _cleanData = $.cleanData; 203 $.cleanData = function (elems) { 204 for (var i = 0, elem; 205 (elem = elems[i]) != null; i++) { 206 $(elem).triggerHandler("remove"); 207 } 208 _cleanData(elems); 209 }; 210 $.widget = function (name, base, prototype) { 211 var namespace = name.split(".")[0], 212 fullName; 213 name = name.split(".")[1]; 214 fullName = namespace + "-" + name; 215 if (!prototype) { 216 prototype = base; 217 base = $.Widget; 218 } 219 // create selector for plugin 220 $.expr[":"][fullName] = function (elem) { 221 return !!$.data(elem, name); 222 }; 223 $[namespace] = $[namespace] || {}; 224 // create the constructor using $.extend() so we can carry over any 225 // static properties stored on the existing constructor (if there is one) 226 $[namespace][name] = $.extend(function (options, element) { 227 // allow instantiation without "new" keyword 228 if (!this._createWidget) { 229 return new $[namespace][name](options, element); 230 } 231 // allow instantiation without initializing for simple inheritance 232 // must use "new" keyword (the code above always passes args) 233 if (arguments.length) { 234 this._createWidget(options, element); 235 } 236 }, $[namespace][name]); 237 var basePrototype = new base(); 238 // we need to make the options hash a property directly on the new instance 239 // otherwise we'll modify the options hash on the prototype that we're 240 // inheriting from 241 basePrototype.options = $.widget.extend({}, basePrototype.options); 242 $.each(prototype, function (prop, value) { 243 if ($.isFunction(value)) { 244 prototype[prop] = (function () { 245 var _super = function (method) { 246 return base.prototype[method].apply(this, slice.call(arguments, 1)); 247 }; 248 var _superApply = function (method, args) { 249 return base.prototype[method].apply(this, args); 250 }; 251 return function () { 252 var __super = this._super, 253 __superApply = this._superApply, 254 returnValue; 255 this._super = _super; 256 this._superApply = _superApply; 257 returnValue = value.apply(this, arguments); 258 this._super = __super; 259 this._superApply = __superApply; 260 return returnValue; 261 }; 262 }()); 263 } 264 }); 265 $[namespace][name].prototype = $.widget.extend(basePrototype, { 266 namespace: namespace, 267 widgetName: name, 268 widgetEventPrefix: name, 269 widgetBaseClass: fullName 270 }, prototype); 271 $.widget.bridge(name, $[namespace][name]); 272 }; 273 $.widget.extend = function (target) { 274 var input = slice.call(arguments, 1), 275 inputIndex = 0, 276 inputLength = input.length, 277 key, value; 278 for (; inputIndex < inputLength; inputIndex++) { 279 for (key in input[inputIndex]) {
280 value = input[inputIndex][key]; 281 if (input[inputIndex].hasOwnProperty(key) && value !== undefined) { 282 target[key] = $.isPlainObject(value) ? $.widget.extend({}, target[key], value) : value; 283 } 284 } 285 } 286 return target; 287 }; 288 $.widget.bridge = function (name, object) { 289 $.fn[name] = function (options) { 290 var isMethodCall = typeof options === "string", 291 args = slice.call(arguments, 1), 292 returnValue = this; 293 // allow multiple hashes to be passed on init 294 options = !isMethodCall && args.length ? $.widget.extend.apply(null, [options].concat(args)) : options; 295 if (isMethodCall) { 296 this.each(function () { 297 var instance = $.data(this, name); 298 if (!instance) { 299 return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'"); 300 } 301 if (!$.isFunction(instance[options]) || options.charAt(0) === "_") { 302 return $.error("no such method '" + options + "' for " + name + " widget instance"); 303 } 304 var methodValue = instance[options].apply(instance, args); 305 if (methodValue !== instance && methodValue !== undefined) { 306 returnValue = methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue; 307 return false; 308 } 309 }); 310 } else { 311 this.each(function () { 312 var instance = $.data(this, name); 313 if (instance) { 314 instance.option(options || {})._init(); 315 } else { 316 object(options, this); 317 } 318 }); 319 } 320 return returnValue; 321 }; 322 }; 323 $.Widget = function (options, element) { 324 // allow instantiation without "new" keyword 325 if (!this._createWidget) { 326 return new $[namespace][name](options, element); 327 } 328 // allow instantiation without initializing for simple inheritance 329 // must use "new" keyword (the code above always passes args) 330 if (arguments.length) { 331 this._createWidget(options, element); 332 } 333 }; 334 $.Widget.prototype = { 335 widgetName: "widget", 336 widgetEventPrefix: "", 337 defaultElement: "<div>", 338 options: { 339 disabled: false, 340 // callbacks 341 create: null 342 }, 343 _createWidget: function (options, element) { 344 element = $(element || this.defaultElement || this)[0]; 345 this.element = $(element); 346 this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options); 347 this.bindings = $(); 348 this.hoverable = $(); 349 this.focusable = $(); 350 if (element !== this) { 351 $.data(element, this.widgetName, this); 352 this._bind({ 353 remove: "destroy" 354 }); 355 } 356 this._create(); 357 this._trigger("create"); 358 this._init(); 359 }, 360 _getCreateOptions: $.noop, 361 _create: $.noop, 362 _init: $.noop, 363 destroy: function () { 364 this._destroy(); 365 // we can probably remove the unbind calls in version 2 366 // all event bindings should go through this._bind() 367 this.element.unbind("." + this.widgetName).removeData(this.widgetName); 368 this.widget().unbind("." + this.widgetName).removeAttr("aria-disabled").removeClass( 369 this.widgetBaseClass + "-disabled " + "ui-state-disabled"); 370 // clean up events and states 371 this.bindings.unbind("." + this.widgetName); 372 this.hoverable.removeClass("ui-state-hover"); 373 this.focusable.removeClass("ui-state-focus"); 374 }, 375 _destroy: $.noop, 376 widget: function () { 377 return this.element; 378 }, 379 option: function (key, value) { 380 var options = key, 381 parts, curOption, i; 382 if (arguments.length === 0) { 383 // don't return a reference to the internal hash 384 return $.widget.extend({}, this.options); 385 } 386 if (typeof key === "string") { 387 if (value === undefined) { 388 return this.options[key]; 389 } 390 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 391 options = {}; 392 parts = key.split("."); 393 key = parts.shift(); 394 if (parts.length) { 395 curOption = options[key] = $.widget.extend({}, this.options[key]); 396 for (i = 0; i < parts.length - 1; i++) { 397 curOption[parts[i]] = curOption[parts[i]] || {}; 398 curOption = curOption[parts[i]]; 399 } 400 curOption[parts.pop()] = value; 401 } else { 402 options[key] = value; 403 } 404 } 405 this._setOptions(options); 406 return this; 407 }, 408 _setOptions: function (options) { 409 var self = this; 410 $.each(options, function (key, value) { 411 self._setOption(key, value); 412 }); 413 return this; 414 }, 415 _setOption: function (key, value) { 416 this.options[key] = value; 417 if (key === "disabled") { 418 this.widget().toggleClass(this.widgetBaseClass + "-disabled ui-state-disabled", !! value).attr("aria-disabled", value); 419 this.hoverable.removeClass("ui-state-hover"); 420 this.focusable.removeClass("ui-state-focus"); 421 } 422 return this; 423 }, 424 enable: function () { 425 return this._setOption("disabled", false); 426 }, 427 disable: function () { 428 return this._setOption("disabled", true); 429 }, 430 _bind: function (element, handlers) { 431 // no element argument, shuffle and use this.element 432 if (!handlers) { 433 handlers = element; 434 element = this.element; 435 } else { 436 // accept selectors, DOM elements 437 element = $(element); 438 this.bindings = this.bindings.add(element); 439 } 440 var instance = this; 441 $.each(handlers, function (event, handler) { 442 element.bind(event + "." + instance.widgetName, function () { 443 // allow widgets to customize the disabled handling 444 // - disabled as an array instead of boolean 445 // - disabled class as method for disabling individual parts 446 if (instance.options.disabled === true || $(this).hasClass("ui-state-disabled")) { 447 return; 448 } 449 return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments); 450 }); 451 }); 452 }, 453 _hoverable: function (element) { 454 this.hoverable = this.hoverable.add(element); 455 this._bind(element, { 456 mouseenter: function (event) { 457 $(event.currentTarget).addClass("ui-state-hover"); 458 }, 459 mouseleave: function (event) { 460 $(event.currentTarget).removeClass("ui-state-hover"); 461 } 462 }); 463 }, 464 _focusable: function (element) { 465 this.focusable = this.focusable.add(element); 466 this._bind(element, { 467 focusin: function (event) { 468 $(event.currentTarget).addClass("ui-state-focus"); 469 }, 470 focusout: function (event) { 471 $(event.currentTarget).removeClass("ui-state-focus"); 472 } 473 }); 474 }, 475 _trigger: function (type, event, data) { 476 var callback = this.options[type], 477 args; 478 event = $.Event(event); 479 event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase(); 480 data = data || {}; 481 // copy original event properties over to the new event 482 // this would happen if we could call $.event.fix instead of $.Event 483 // but we don't have a way to force an event to be fixed multiple times 484 if (event.originalEvent) { 485 for (var i = $.event.props.length, prop; i;) { 486 prop = $.event.props[--i]; 487 event[prop] = event.originalEvent[prop]; 488 } 489 } 490 this.element.trigger(event, data); 491 args = $.isArray(data) ? [event].concat(data) : [event, data]; 492 return !($.isFunction(callback) && callback.apply(this.element[0], args) === false || event.isDefaultPrevented()); 493 } 494 }; 495 $.each({ 496 show: "fadeIn", 497 hide: "fadeOut" 498 }, function (method, defaultEffect) { 499 $.Widget.prototype["_" + method] = function (element, options, callback) { 500 options = options || {}; 501 var hasOptions = !$.isEmptyObject(options), 502 effectName = options.effect || defaultEffect; 503 options.complete = callback; 504 if (options.delay) { 505 element.delay(options.delay); 506 } 507 if (hasOptions && $.effects && ($.effects.effect[effectName] || $.uiBackCompat !== false && $.effects[effectName])) { 508 element[method](options); 509 } else if (effectName !== method && element[effectName]) { 510 element[effectName](options.duration, options.easing, callback); 511 } else { 512 element.queue(function () { 513 $(this)[method](); 514 if (callback) { 515 callback.call(element[0]); 516 } 517 }); 518 } 519 }; 520 }); 521 // DEPRECATED 522 if ($.uiBackCompat !== false) { 523 $.Widget.prototype._getCreateOptions = function () { 524 return $.metadata && $.metadata.get(this.element[0])[this.widgetName]; 525 }; 526 } 527})(jQuery); 528 529/* 530 SlidesJS, let the good times roll 531*/ 532(function($) { 533 $.widget("js.slides", { 534 options: { 535 width: 780, // [Number] Define the slide width 536 responsive: false, // [Boolean] slideshow will scale to its container 537 height: 221, // [Number] Define the slide height 538 navigation: true, // [Boolean] Auto generate the naviagation, next/previous buttons 539 pagination: true, // [Boolean] Auto generate the pagination 540 effects: { 541 navigation: "slide", // [String] Can be either "slide" or "fade" 542 pagination: "slide" // [String] Can be either "slide" or "fade" 543 }, 544 direction: "left", // [String] Define the slide direction: "Up", "Right", "Down", "left" 545 fade: { 546 interval: 1000, // [Number] Interval of fade in milliseconds 547 crossfade: false, // [Boolean] TODO: add this feature. Crossfade the slides, great for images, bad for text 548 easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/> 549 }, 550 slide: { 551 interval: 1000, // [Number] Interval of fade in milliseconds 552 browserWindow: false, // [Boolean] Slide in/out from browser window, bad ass 553 easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/> 554 }, 555 preload: { 556 active: false, // [Boolean] Preload the slides before showing them, this needs some work 557 image: "../img/loading.gif" // [String] Define the path to a load .gif, yes I should do something cooler 558 }, 559 startAtSlide: 1, // [Number] What should the first slide be? 560 playInterval: 5000, // [Number] Time spent on each slide in milliseconds 561 pauseInterval: 8000, // [Number] Time spent on pause, triggered on any navigation or pagination click 562 autoHeight: false, // [Boolean] TODO: add this feature. Auto sets height based on each slide 563 navigateStart: function( current ){ 564 // console.log( "navigateStart: ", current ); 565 }, 566 navigateEnd: function( current ){ 567 // console.log( "navigateEnd: ", current ); 568 }, 569 loaded: function() { 570 // console.log( "loaded" ); 571 } 572 }, 573 _create: function() { 574
575 // Error correction for only 1 slide 576 if (this.element.children().length < 2) { 577 return; 578 } 579 580 if ( this.options.slide.browserWindow ) { 581 this.element.css({ 582 width: window.innerWidth, 583 position: "relative", 584 left: - (window.innerWidth / 2) + (this.options.width / 2), 585 overflow: "hidden" 586 }); 587 588 $(window).resize( $.proxy(function() { 589 this.element.css({ 590 width: window.innerWidth, 591 left: - (window.innerWidth / 2) + (this.options.width / 2) 592 }); 593 594 this.slidesContainer.css({ 595 left: this.options.slide.browserWindow ? (window.innerWidth - this.options.width) / 2 : "" 596 }); 597 },this)); 598 } 599 600 this.slidesContainer = this.element.children().not(".slidesNavigation").wrapAll( "<div class='slidesContainer'>" ).parent().css({ 601 width: this.options.responsive ? "100%" : this.options.width, 602 height: this.options.height, 603 overflow: this.options.slide.browserWindow ? "visible" : "hidden", 604 position: "relative", 605 left: this.options.slide.browserWindow ? (window.innerWidth - this.options.width) / 2 : "" 606 }); 607 608 this.slidesControl = this.slidesContainer.wrapInner( "<div class='slidesControl'>" ).children().css({ 609 display: "none" 610 }); 611 612 // Define the slides 613 this.slides = this.slidesControl.children(); 614 615 // Set CSS for slidesControl 616 this.slidesControl.css({ 617 position: "relative", 618 width: this.options.responsive ? "100%" : this.options.width, 619 height: this.options.height, 620 left: 0 621 }); 622 623 // Set CSS for each slide 624 this.slides.css({ 625 position: "absolute", 626 top: 0, 627 left: 0, 628 zIndex: 0, 629 display: "none" 630 }); 631 632 // Show the starting slide with a fade in 633 this.slides.eq( this.options.startAtSlide - 1 ).fadeIn( this.options.fade.interval ); 634 635 if ( this.options.preload.active ) { 636 637/* TODO: loading image, need to remove on load callback 638 639 this.slidesContainer.css({ 640 backgroundImage: "url(" + this.options.preload.image + ")", 641 backgroundPosition: "50% 50%", 642 backgroundRepeat: "no-repeat" 643 }); 644*/ 645 var preloadImage; 646 647 if (this.slides.eq( this.options.startAtSlide - 1 ).is("img")) { 648 preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).attr("src"); 649 } else { 650 preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).find("img").attr("src"); 651 } 652 653 this._loadImage( preloadImage ).then( $.proxy(function( url ) { 654 this.slidesControl.fadeIn( this.options.fade.interval ); 655 this._trigger( "loaded", this.options.startAtSlide, this ); 656 },this)); 657 } else { 658 this.slidesControl.fadeIn( this.options.fade.interval ); 659 } 660 661 if ( this.options.navigation ) { 662 this.prevButton = $("<a>",{ 663 "class": "slidesPrevious slidesNavigation", 664 href: "#", 665 title: "Previous", 666 text: "Previous" 667 }).appendTo( this.element ); 668 669 this.nextButton = $("<a>",{ 670 "class": "slidesNext slidesNavigation", 671 href: "#", 672 title: "Next", 673 text: "Next" 674 }).appendTo( this.element ); 675 } else { 676 this.nextButton = $(".slidesNext"); 677 this.prevButton = $(".slidesPrevious"); 678 } 679 680 if (this.options.pagination) { 681 this._buildPagination(); 682 // add current class to first pagination 683 this.pagination.children().eq( this.options.startAtSlide - 1 ).addClass("slidesCurrent"); 684 } 685 686 this.current = this.options.startAtSlide - 1; 687 688 this.element.delegate( ".slidesNavigation", "click", $.proxy(this, "_navigate") ); 689 690 this.total = this.slides.length; 691 }, 692 _loaded: function() { 693 if ( this.options.responsive ) { 694 695 // TODO: cleanup and condense 696 this.slidesContainer.css({ 697 height: this.slides.height() 698 }); 699 700 this.slidesControl.css({ 701 height: this.slides.height() 702 }); 703 704 $(window).resize( $.proxy(function() { 705 this.slidesContainer.css({ 706 height: this.slides.height() 707 }); 708 this.slidesControl.css({ 709 height: this.slides.height() 710 }); 711 },this)); 712 } 713 }, 714 _buildPagination: function() { 715 716 if (this.pagination) { 717 // Remove the current paginaiton 718 this.pagination.remove(); 719 // Redefine slides with new children 720 this.slides = this.slidesControl.children(); 721 } 722 723 this.pagination = $("<ul>",{ 724 "class": "slidesPagination" 725 }).appendTo(this.element); 726 727 this.slides.each( 728 $.proxy(function(index, element) { 729 $("<li><a href='#" + index + "' class='slidesNavigation slidesPaginationItem' data-sli
729desindex=" + index + "> " + ( index + 1 ) + "</a></li>").appendTo(this.pagination); 730 },this) 731 ); 732 733 }, 734 _loadImage: function(imageSrc) { 735 var deferred, preloader; 736 var loadImageCache = {}; 737 if (typeof loadImageCache[imageSrc] === "undefined") { 738 deferred = $.Deferred(); 739 740 preloader = new Image(); 741 preloader.onload = function() { 742 deferred.resolve(this.src); 743 }; 744 preloader.onerror = function() { 745 deferred.reject(this.src); 746 }; 747 preloader.src = imageSrc; 748 749 loadImageCache[imageSrc] = deferred; 750 } 751 752 return loadImageCache[imageSrc]; 753 }, 754 next: function( effect ) { 755 this._navigate("next", effect); 756 }, 757 previous: function( effect ) { 758 this._navigate("previous", effect); 759 }, 760 slide: function( slide, effect ) { 761 this.element.data("goto", (slide - 1)); 762 this._navigate("pagination", effect); 763 }, 764 _navigate: function( event, effect ) { 765 var to, position, direction, next, prev, pagination, $target = $(event.target), currentSlide = this.slides.eq( this.current ); 766 767 /* 768 Slide to error correction 769 */ 770 if ( this.element.data("goto") < 0 ) { 771 // If goto is less then 0 772 this.element.data("goto",0); 773 } else if ( this.element.data("goto") > this.total ) { 774 // If goto is greater then total slides 775 this.element.data("goto",(this.total - 1)); 776 } 777 778 /* 779 Check if slides is currently animating 780 */ 781 if ( this.element.data("animated") || $target.data("slidesindex") === this.current || this.element.data("goto") === this.current ) { 782 return false; 783 } 784 785 /* 786 Is this event coming from a click? 787 */ 788 if (typeof(event) === "object") { 789 event.preventDefault(); 790 791 // Pause on navigation item click 792 if ( this.state === "playing" && this.options.pauseInterval ) { 793 this.pause(); 794 } 795 } else { 796 if (event === "next") { 797 next = true; 798 } else { 799 prev = true; 800 } 801 } 802 803 /* 804 Set to animated 805 */ 806 this.element.data("animated",true); 807 808 if ( $target.hasClass( "slidesNext" ) ) { 809 // Next button clicked 810 next = true; 811 812 } else if ( $target.hasClass("slidesPrevious") ) { 813 814 // Previous button clicked 815 prev = true; 816 817 } else if ( $target.hasClass("slidesPaginationItem") || event === "pagination") { 818 819 // Paginaiton item clicked 820 if ( this.current > $target.data("slidesindex") || this.current > this.element.data("goto") ) { 821 prev = true; 822 } else { 823 next = true; 824 } 825 826 pagination = true; 827 828 effect = effect ? effect : this.options.effects.pagination; 829 } 830 831 if (pagination) { 832 // Get next from data-slidesindex 833 to = this.element.data("goto") > -1 ? this.element.data("goto") : $target.data("slidesindex"); 834 } else { 835 // Get next based on curent 836 to = next ? (this.current + 1) : (prev ? this.current - 1 : this.current); 837 } 838 839 // Pass slide from number 840 this._trigger("navigateStart", ( this.current + 1 ), this); 841 842 // creat the loop 843 if ( to == this.slides.length && !pagination ) { 844 // last slide, loop to first 845 to = 0; 846 } else if ( to == -1 && !pagination ) { 847 // first slide, loop to last 848 to = this.slides.length - 1; 849 } 850 851 if (this.options.pagination) { 852 // Change the pagination 853 this.pagination.children().removeClass("slidesCurrent"); 854 this.pagination.children().eq( to ).addClass("slidesCurrent"); 855 } 856 857 // Effects methods 858 if (effect === "fade") { 859 this._fade({ 860 next: next, 861 to: to, 862 currentSlide: currentSlide 863 }); 864 } else { 865 this._slide({ 866 next: next, 867 to: to, 868 currentSlide: currentSlide 869 }); 870 } 871 }, 872 _slide: function (navigateData) { 873 /* 874 Thanks to Thomas Reynolds <http://awardwinningfjords.com/> 875 */ 876 877 var isFlipped = navigateData.next ? 1 : -1; 878 var isOpposite = this.options.direction.match(/right|down/) ? -1 : 1; 879 var type = this.options.direction.match(/left|right/) ? "horizontal" : "vertical"; 880 var vector = (type == "horizontal") ? "width" : "height"; 881 882 vector = this.options.responsive ? this.slides.width() : this.options[vector] ; 883 884 var position = vector * isOpposite * isFlipped; 885 886 if (this.options.slide.browserWindow) { 887 if (navigateData.next) { 888 position = Math.abs( this.options.width - window.innerWidth - position); 889 } else { 890 position = this.options.width - window.innerWidth + position; 891 } 892 } 893 894 var direction = position * -1; 895 896 // Setup the "to" slide 897 this.slides.eq( navigateData.to ).css({ 898 left: type === "vertical" ? 0 : position, 899 top: type === "vertical" ? position : 0, 900 zIndex: 5, 901 display: "block" 902 }); 903 904 // animate control 905 this.slidesControl.animate({ 906 left: type === "vertical" ? 0 : direction, 907 top: type === "vertical" ? direction : 0 908 },this.options.slide.interval, this.options.slide.easing, $.proxy(function(){ 909 // after animation reset control position 910 this.slidesControl.css({ 911 top: 0, 912 left:0 913 }); 914 // reset and show next 915 this.slides.eq( navigateData.to ).css({ 916 top: 0, 917 left:0, 918 zIndex: 5 919 }); 920 921 // reset previous slide 922 navigateData.currentSlide.css({ 923 top: 0, 924 left:0, 925 display: "none", 926 zIndex: 0 927 }); 928 929 this.current = navigateData.to; 930 931 this._trigger("navigateEnd", ( this.current + 1 ), this); 932 }, this)); 933 }, 934 _fade: function (navigateData) { 935 936 // put hidden to slide above current 937 this.slides.eq( navigateData.to ).css({ 938 zIndex: 10 939 // fade in next 940 }).fadeIn(this.options.fade.interval, this.options.fade.easing, $.proxy(function(){ 941 942 // hide previous 943 navigateData.currentSlide.css({ 944 display: "none", 945 zIndex: 0 946 }); 947 948 // reset zindex 949 this.slides.eq( navigateData.to ).css({ 950 zIndex: 0 951 }); 952 953 this.current = navigateData.to; 954 955 this._trigger("navigateEnd", ( this.current + 1 ), this); 956 957 }, this)); 958 }, 959 play: function( gotoNext ) { 960 if (gotoNext !== false) { 961 this._navigate("next"); 962 } 963 964 var playInterval = setInterval( $.proxy(function() { 965 this._navigate("next"); 966 }, this), this.options.playInterval); 967 968 // Set status 969 this.state = "playing"; 970 971 // Store the unique interval ID 972 this.element.data("playIntervalId",playInterval); 973 }, 974 pause: function() { 975 clearTimeout( this.element.data("pauseTimeoutId") ); 976 977 clearInterval( this.element.data("playIntervalId") ); 978 979 var pauseTimeout = setTimeout($.proxy(function() { 980 this.play(); 981 }, this), this.options.pauseInterval); 982 983 // Set status 984 this.state = "paused"; 985 986 // Store the unique pause timeout ID 987 this.element.data("pauseTimeoutId",pauseTimeout); 988 }, 989 stop: function() { 990 clearInterval( this.element.data("playIntervalId") ); 991 992 // Set status 993 this.state = "stopped"; 994 }, 995 update: function() { 996 this._buildPagination(); 997 }, 998 status: function( key ) { 999 if (key) { 1000 return this[key] ? this[key] : false;
1001 } else { 1002 return { 1003 "state": this.state, 1004 "current": this.current, 1005 "total": this.total 1006 }; 1007 } 1008 1009 }, 1010 _setOption: function(key, value) { 1011 switch(key) { 1012 /* 1013 TODO: This needs work, note status function use of this[key] 1014 $("#slides").slides("option","pagination", false); 1015 1016 case "pagination": 1017 if (value !== this.options.pagination ) { 1018 value ? this._buildPagination() : this.pagination.remove(); 1019 } 1020 break; 1021 */ 1022 } 1023 $.Widget.prototype._setOption.apply(this,arguments); 1024 }, 1025 destroy: function() { 1026 1027 this.slidesContainer.contents().unwrap(); 1028 1029 this.slidesControl.contents().unwrap(); 1030 1031 this.element.unbind(); 1032 1033 this.pagination.remove(); 1034 1035 this.nextButton.remove(); 1036 1037 this.prevButton.remove(); 1038 1039 this.slides.attr( "style", "" ); 1040 1041 $.Widget.prototype.destroy.call(this); 1042 }, 1043 _trigger: function( event, current ) { 1044 if (event != "create") { 1045 this.options[event]( current ); 1046 } 1047 if (event === "navigateEnd") { 1048 this.element.data("animated",false); 1049 } 1050 if (event === "loaded") { 1051 this._loaded(); 1052 } 1053 } 1054 }); 1055})(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.