1/*! 2 * jQuery.BgSwitcher 3 * 4 * @version 0.4.3 5 * @author rewish <[email protected]> 6 * @license MIT License (https://github.com/rewish/jquery-bgswitcher/blob/master/LICENSE.md) 7 * @link https://github.com/rewish/jquery-bgswitcher 8 */ 9(function($) { 10 'use strict'; 11 12 var loadedImages = {}, 13 14 slice = Array.prototype.slice, 15 toString = Object.prototype.toString, 16 17 corners = ['Top', 'Right', 'Bottom', 'Left'], 18 backgroundProperties = [ 19 'Attachment', 'Color', 'Image', 'Repeat', 20 'Position', 'Size', 'Clip', 'Origin' 21 ]; 22 23 $.fn.bgswitcher = function() { 24 var args = arguments, 25 instanceKey = BgSwitcher.keys.instance; 26 27 return this.each(function() { 28 var instance = $.data(this, instanceKey); 29 30 if (!instance) { 31 instance = new BgSwitcher(this); 32 $.data(this, instanceKey, instance); 33 } 34 35 instance.dispatch.apply(instance, args); 36 }); 37 }; 38 39 // Backward Compatibility 40 $.fn.bgSwitcher = $.fn.bgswitcher; 41 42 /** 43 * BgSwitcher 44 * 45 * @param {HTMLElement} el 46 * @constructor 47 */ 48 function BgSwitcher(el) { 49 this.$el = $(el); 50 this.index = 0; 51 this.config = $.extend({}, BgSwitcher.defaultConfig); 52 53 this._setupBackgroundElement(); 54 this._listenToResize(); 55 } 56 57 $.extend(BgSwitcher.prototype, { 58 /** 59 * Dispatch 60 * 61 * @param {string|Array} one 62 */ 63 dispatch: function(one) { 64 switch (toString.call(one)) { 65 case '[object Object]': 66 this.setConfig(one); 67 break; 68 case '[object String]': 69 this[one].apply(this, slice.call(arguments, 1)); 70 break; 71 default: 72 throw new Error('Please specify a Object or String'); 73 } 74 }, 75 76 /** 77 * Set config 78 * 79 * @param {Object} config 80 */ 81 setConfig: function(config) { 82 this.config = $.extend(this.config, config); 83 84 if (typeof this.config.random !== 'undefined') { 85 this.config.shuffle = this.config.random; 86 } 87 88 this.refresh(); 89 }, 90 91 /** 92 * Set images 93 * 94 * @param {Array} images 95 */ 96 setImages: function(images) { 97 this.imageList = new this.constructor.ImageList(images); 98 99 if (this.config.shuffle) { 100 this.imageList.shuffle(); 101 } 102 }, 103 104 /** 105 * Set switch handler 106 * 107 * @param {Function} fn 108 */ 109 setSwitchHandler: function(fn) { 110 this.switchHandler = $.proxy(fn, this); 111 }, 112 113 /** 114 * Default switch handler 115 * 116 * @param {string} type 117 * @returns {Function} 118 */ 119 getBuiltInSwitchHandler: function(type) { 120 return this.constructor.switchHandlers[type || this.config.effect]; 121 }, 122 123 /** 124 * Refresh 125 */ 126 refresh: function() { 127 this.setImages(this.config.images); 128 this.setSwitchHandler(this.getBuiltInSwitchHandler()); 129 this._prepareSwitching(); 130 131 if (this.config.start) { 132 this.start(); 133 } 134 }, 135 136 /** 137 * Start switching 138 */ 139 start: function() { 140 if (!this._timerID) { 141 this._timerID = setTimeout($.proxy(this, 'next'), this.config.interval); 142 } 143 }, 144 145 /** 146 * Stop switching 147 */ 148 stop: function() { 149 if (this._timerID) { 150 clearTimeout(this._timerID); 151 this._timerID = null; 152 } 153 }, 154 155 /** 156 * Toggle between start/stop 157 */ 158 toggle: function() { 159 if (this._timerID) { 160 this.stop(); 161 } else { 162 this.start(); 163 } 164 }, 165 166 /** 167 * Reset switching 168 */ 169 reset: function() { 170 this.index = 0; 171 this._prepareSwitching(); 172 }, 173 174 /** 175 * Go to next switching 176 */ 177 next: function() { 178 var max = this.imageList.count(); 179 180 if (!this.config.loop && this.index + 1 === max) { 181 return; 182 } 183 184 if (++this.index === max) { 185 this.index = 0; 186 } 187 188 this.switching(); 189 }, 190 191 /** 192 * Go to previous switching 193 */ 194 prev: function() { 195 if (!this.config.loop && this.index === 0) { 196 return; 197 } 198 199 if (--this.index === -1) { 200 this.index = this.imageList.count() - 1; 201 } 202 203 this.switching(); 204 }, 205 206 /** 207 * Select the switching at index 208 * 209 * @param {number} index 210 */ 211 select: function(index) { 212 if (index === -1) { 213 index = this.imageList.count() - 1; 214 } 215 216 this.index = index; 217 this.switching(); 218 }, 219 220 /** 221 * Switching the background image 222 */ 223 switching: function() { 224 var started = !!this._timerID; 225 226 if (started) { 227 this.stop(); 228 } 229 230 this._createSwitchableElement(); 231 this._prepareSwitching(); 232 this.switchHandler(this.$switchable); 233 234 if (started) { 235 this.start(); 236 } 237 }, 238 239 /** 240 * Destroy... 241 */ 242 destroy: function() { 243 this.stop(); 244 this._stopListeningToResize(); 245 246 if (this.$switchable) { 247 this.$switchable.stop(); 248 this.$switchable.remove(); 249 this.$switchable = null; 250 } 251 252 if (this.$bg) { 253 this.$bg.remove(); 254 this.$bg = null; 255 } 256 257 this.$el.removeAttr('style'); 258 this.$el.removeData(this.constructor.keys.instance); 259 this.$el = null; 260 }, 261 262 /** 263 * Adjust rectangle 264 */ 265 _adjustRectangle: function() { 266 var corner, 267 i = 0, 268 length = corners.length, 269 offset = this.$el.position(), 270 copiedStyles = { 271 top: offset.top, 272 left: offset.left, 273 width: this.$el.innerWidth(),
274 height: this.$el.innerHeight() 275 }; 276 277 for (; i < length; i++) { 278 corner = corners[i]; 279 copiedStyles['margin' + corner] = this.$el.css('margin' + corner); 280 copiedStyles['border' + corner] = this.$el.css('border' + corner); 281 } 282 copiedStyles['background-size'] = 'cover'; 283 copiedStyles['background-repeat'] = 'no-repeat'; 284 this.$bg.css(copiedStyles); 285 }, 286 287 /** 288 * Setup background element 289 */ 290 _setupBackgroundElement: function() { 291 this.$bg = $(document.createElement('div')); 292 this.$bg.addClass('slider_content'); 293 this.$bg.css({ 294 position: 'absolute', 295 zIndex: (parseInt(this.$el.css('zIndex'), 10) || 0) - 1, 296 overflow: 'hidden' 297 }); 298 299 this._copyBackgroundStyles(); 300 this._adjustRectangle(); 301 302 if (this.$el[0].tagName === 'BODY') { 303 this.$el.prepend(this.$bg); 304 } else { 305 this.$el.before(this.$bg); 306 this.$el.css('background', 'none'); 307 } 308 }, 309 310 /** 311 * Create switchable element 312 */ 313 _createSwitchableElement: function() { 314 if (this.$switchable) { 315 this.$switchable.remove(); 316 } 317 318 this.$switchable = this.$bg.clone(); 319 this.$switchable.css({top: 0, left: 0, margin: 0, border: 'none'}); 320 this.$switchable.appendTo(this.$bg); 321 }, 322 323 /** 324 * Copy background styles 325 */ 326 _copyBackgroundStyles: function () { 327 var prop, 328 copiedStyle = {}, 329 i = 0, 330 length = backgroundProperties.length, 331 backgroundPosition = 'backgroundPosition'; 332 333 for (; i < length; i++) { 334 prop = 'background' + backgroundProperties[i]; 335 copiedStyle[prop] = this.$el.css(prop); 336 } 337 338 // For IE<=9 339 if (copiedStyle[backgroundPosition] === undefined) { 340 copiedStyle[backgroundPosition] = [ 341 this.$el.css(backgroundPosition + 'X'), 342 this.$el.css(backgroundPosition + 'Y') 343 ].join(' '); 344 } 345 346 this.$bg.css(copiedStyle); 347 }, 348 349 /** 350 * Listen to the resize event 351 */ 352 _listenToResize: function() { 353 var that = this; 354 this._resizeHandler = function() { 355 that._adjustRectangle(); 356 }; 357 $(window).on('resize', this._resizeHandler); 358 }, 359 360 /** 361 * Stop listening to the resize event 362 */ 363 _stopListeningToResize: function() { 364 $(window).off('resize', this._resizeHandler); 365 this._resizeHandler = null; 366 }, 367 368 /** 369 * Prepare the Switching 370 */ 371 _prepareSwitching: function() { 372 this.$bg.css('backgroundImage', this.imageList.url(this.index)); 373 } 374 }); 375 376 /** 377 * Data Keys 378 * @type {Object} 379 */ 380 BgSwitcher.keys = { 381 instance: 'bgSwitcher' 382 }; 383 384 /** 385 * Default Config 386 * @type {Object} 387 */ 388 BgSwitcher.defaultConfig = { 389 images: [], 390 interval: 5000, 391 start: true, 392 loop: true, 393 shuffle: false, 394 effect: 'fade', 395 duration: 1000, 396 easing: 'swing' 397 }; 398 399 /** 400 * Built-In switch handlers (effects) 401 * @type {Object} 402 */ 403 BgSwitcher.switchHandlers = { 404 fade: function($el) { 405 $el.animate({opacity: 0}, this.config.duration, this.config.easing); 406 }, 407 408 blind: function($el) { 409 $el.animate({height: 0}, this.config.duration, this.config.easing); 410 }, 411 412 clip: function($el) { 413 $el.animate({ 414 top: parseInt($el.css('top'), 10) + $el.height() / 2, 415 height: 0 416 }, this.config.duration, this.config.easing); 417 }, 418 419 slide: function($el) { 420 $el.animate({top: -$el.height()}, this.config.duration, this.config.easing); 421 }, 422 423 drop: function($el) { 424 $el.animate({ 425 left: -$el.width(), 426 opacity: 0 427 }, this.config.duration, this.config.easing); 428 }, 429 430 hide: function($el) { 431 $el.hide(); 432 } 433 }; 434 435 /** 436 * Define effect 437 * 438 * @param {String} name 439 * @param {Function} fn 440 */ 441 BgSwitcher.defineEffect = function(name, fn) { 442 this.switchHandlers[name] = fn; 443 }; 444 445 /** 446 * BgSwitcher.ImageList 447 * 448 * @param {Array} images 449 * @constructor 450 */ 451 BgSwitcher.ImageList = function(images) { 452 this.images = images; 453 this.createImagesBySequence(); 454 this.preload(); 455 }; 456 457 $.extend(BgSwitcher.ImageList.prototype, { 458 /** 459 * Images is sequenceable 460 * 461 * @returns {boolean} 462 */ 463 isSequenceable: function() { 464 return typeof this.images[0] === 'string' && 465 typeof this.images[1] === 'number' && 466 typeof this.images[2] === 'number'; 467 }, 468 469 /** 470 * Create an images by sequence 471 */ 472 createImagesBySequence: function() { 473 if (!this.isSequenceable()) { 474 return; 475 } 476 477 var images = [], 478 base = this.images[0], 479 min = this.images[1], 480 max = this.images[2]; 481 482 do { 483 images.push(base.replace(/\.\w+$/, min + '$&')); 484 } while (++min <= max); 485 486 this.images = images; 487 }, 488 489 /** 490 * Preload an images 491 */ 492 preload: function() { 493 var path, 494 length = this.images.length, 495 i = 0; 496 497 for (; i < length; i++) { 498 path = this.images[i]; 499 if (!loadedImages[path]) { 500 loadedImages[path] = new Image(); 501 loadedImages[path].src = path; 502 } 503 } 504 }, 505 506 /** 507 * Shuffle an images 508 */ 509 shuffle: function() { 510 var j, t, 511 i = this.images.length, 512 original = this.images.join(); 513 514 if (!i) { 515 return; 516 } 517 518 while (i) { 519 j = Math.floor(Math.random() * i); 520 t = this.images[--i]; 521 this.images[i] = this.images[j]; 522 this.images[j] = t; 523 } 524 525 if (this.images.join() === original) { 526 this.shuffle(); 527 } 528 }, 529 530 /** 531 * Get the image from index 532 * 533 * @param {number} index 534 * @returns {string} 535 */ 536 get: function(index) { 537 return this.images[index]; 538 }, 539 540 /** 541 * Get the URL with function of CSS 542 * 543 * @param {number} index 544 * @returns {string} 545 */ 546 url: function(index) { 547 return 'url(' + this.get(index) + ')'; 548 }, 549 550 /** 551 * Count of images 552 * 553 * @returns {number} 554 */ 555 count: function() { 556 return this.images.length; 557 } 558 }); 559 560 $.BgSwitcher = BgSwitcher; 561}(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.