1/*! 2 * jQuery.BgSwitcher 3 * 4 * @version 0.4.1 5 * @author rewish <[email protected]> 6 * @license MIT License (https://github.com/rewish/jquery-bgswitcher/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 edges = ['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._prepare(); 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 * Adjust rectangle 125 */ 126 adjustRectangle: function() { 127 var edge, 128 i = 0, 129 length = edges.length, 130 offset = this.$el.position(); 131 var top = offset.top; 132 if (offset.top === 86) { 133 top = 56; 134 } 135 var copiedStyles = { 136 top: top,//offset.top, 137 left: offset.left, 138 width: this.$el.innerWidth(),
139 height: this.$el.innerHeight() 140 }; 141 142 for (; i < length; i++) { 143 edge = edges[i]; 144 copiedStyles['margin' + edge] = this.$el.css('margin' + edge); 145 copiedStyles['border' + edge] = this.$el.css('border' + edge); 146 } 147 148 this.$bg.css(copiedStyles); 149 }, 150 151 /** 152 * Start switching 153 */ 154 start: function() { 155 if (!this._timerID) { 156 this._timerID = setTimeout($.proxy(this, 'next'), this.config.interval); 157 } 158 }, 159 160 /** 161 * Stop switching 162 */ 163 stop: function() { 164 if (this._timerID) { 165 clearTimeout(this._timerID); 166 this._timerID = null; 167 } 168 }, 169 170 /** 171 * Toggle between start/stop 172 */ 173 toggle: function() { 174 if (this._timerID) { 175 this.stop(); 176 } else { 177 this.start(); 178 } 179 }, 180 181 /** 182 * Reset switching 183 */ 184 reset: function() { 185 this.index = 0; 186 this._prepareSwitching(); 187 }, 188 189 /** 190 * Go to next switching 191 */ 192 next: function() { 193 var max = this.imageList.count(); 194 195 if (!this.config.loop && this.index + 1 === max) { 196 return; 197 } 198 199 if (++this.index === max) { 200 this.index = 0; 201 } 202 203 this.switching(); 204 }, 205 206 /** 207 * Go to previous switching 208 */ 209 prev: function() { 210 if (!this.config.loop && this.index === 0) { 211 return; 212 } 213 214 if (--this.index === -1) { 215 this.index = this.imageList.count() - 1; 216 } 217 218 this.switching(); 219 }, 220 221 /** 222 * Switching the background image 223 */ 224 switching: function() { 225 var started = !!this._timerID; 226 227 if (started) { 228 this.stop(); 229 } 230 231 this._createSwitchableElement(); 232 this._prepareSwitching(); 233 this.switchHandler(this.$switchable); 234 235 if (started) { 236 this.start(); 237 } 238 }, 239 240 /** 241 * Destroy... 242 */ 243 destroy: function() { 244 this.stop(); 245 this._stopListeningToResize(); 246 247 if (this.$switchable) { 248 this.$switchable.stop(); 249 this.$switchable.remove(); 250 this.$switchable = null; 251 } 252 253 if (this.$bg) { 254 this.$bg.remove(); 255 this.$bg = null; 256 } 257 258 this.$el.removeAttr('style'); 259 this.$el.removeData(this.constructor.keys.instance); 260 this.$el = null; 261 }, 262 263 /** 264 * Prepare 265 */ 266 _prepare: function() { 267 this.setImages(this.config.images); 268 this.setSwitchHandler(this.getBuiltInSwitchHandler()); 269 this._prepareSwitching(); 270 271 if (this.config.start) { 272 this.start(); 273 } 274 }, 275 276 /** 277 * Setup background element 278 */ 279 _setupBackgroundElement: function() { 280 this.$bg = $(document.createElement('div')); 281 this.$bg.css({ 282 position: 'absolute', 283 zIndex: (parseInt(this.$el.css('zIndex'), 10) || 0) - 1, 284 overflow: 'hidden' 285 }); 286 287 this._copyBackgroundStyles(); 288 this.adjustRectangle(); 289 290 if (this.$el[0].tagName === 'BODY') { 291 this.$el.prepend(this.$bg); 292 } else { 293 this.$el.before(this.$bg); 294 this.$el.css('background', 'none'); 295 } 296 }, 297 298 /** 299 * Create switchable element 300 */ 301 _createSwitchableElement: function() { 302 if (this.$switchable) { 303 this.$switchable.remove(); 304 } 305 306 this.$switchable = this.$bg.clone(); 307 this.$switchable.css({top: 0, left: 0, margin: 0, border: 'none'}); 308 this.$switchable.appendTo(this.$bg); 309 }, 310 311 /** 312 * Copy background styles 313 */ 314 _copyBackgroundStyles: function () { 315 var prop, 316 copiedStyle = {}, 317 length = backgroundProperties.length, 318 i = 0; 319 320 for (; i < length; i++) { 321 prop = 'background' + backgroundProperties[i]; 322 copiedStyle[prop] = this.$el.css(prop); 323 } 324 325 this.$bg.css(copiedStyle); 326 }, 327 328 /** 329 * Listen to the resize event 330 */ 331 _listenToResize: function() { 332 var that = this; 333 this._resizeHandler = function() { 334 that.adjustRectangle(); 335 }; 336 $(window).on('resize', this._resizeHandler); 337 }, 338 339 /** 340 * Stop listening to the resize event 341 */ 342 _stopListeningToResize: function() { 343 $(window).off('resize', this._resizeHandler); 344 this._resizeHandler = null; 345 }, 346 347 /** 348 * Prepare to switching the background image 349 */ 350 _prepareSwitching: function() { 351 this.$bg.css('backgroundImage', this.imageList.url(this.index)); 352 } 353 }); 354 355 /** 356 * Data Keys 357 * @type {Object} 358 */ 359 BgSwitcher.keys = { 360 instance: 'bgSwitcher' 361 }; 362 363 /** 364 * Default Config 365 * @type {Object} 366 */ 367 BgSwitcher.defaultConfig = { 368 images: [], 369 interval: 5000, 370 start: true, 371 loop: true, 372 shuffle: false, 373 effect: 'fade', 374 duration: 1000, 375 easing: 'swing' 376 }; 377 378 /** 379 * Built-In switch handlers (effects) 380 * @type {Object} 381 */ 382 BgSwitcher.switchHandlers = { 383 fade: function($el) { 384 $el.animate({opacity: 0}, this.config.duration, this.config.easing); 385 }, 386 387 blind: function($el) { 388 $el.animate({height: 0}, this.config.duration, this.config.easing); 389 }, 390 391 clip: function($el) { 392 $el.animate({ 393 top: parseInt($el.css('top'), 10) + $el.height() / 2, 394 height: 0 395 }, this.config.duration, this.config.easing); 396 }, 397 398 slide: function($el) { 399 $el.animate({top: -$el.height()}, this.config.duration, this.config.easing); 400 }, 401 402 drop: function($el) { 403 $el.animate({ 404 left: -$el.width(), 405 opacity: 0 406 }, this.config.duration, this.config.easing); 407 }, 408 409 hide: function($el) { 410 $el.hide(); 411 } 412 }; 413 414 /** 415 * Define effect
416 * 417 * @param {String} name 418 * @param {Function} fn 419 */ 420 BgSwitcher.defineEffect = function(name, fn) { 421 this.switchHandlers[name] = fn; 422 }; 423 424 /** 425 * BgSwitcher.ImageList 426 * 427 * @param {Array} images 428 * @constructor 429 */ 430 BgSwitcher.ImageList = function(images) { 431 this.images = images; 432 this.createImagesBySequence(); 433 this.preload(); 434 }; 435 436 $.extend(BgSwitcher.ImageList.prototype, { 437 /** 438 * Images is sequenceable 439 * 440 * @returns {boolean} 441 */ 442 isSequenceable: function() { 443 return typeof this.images[0] === 'string' && 444 typeof this.images[1] === 'number' && 445 typeof this.images[2] === 'number'; 446 }, 447 448 /** 449 * Create an images by sequence 450 */ 451 createImagesBySequence: function() { 452 if (!this.isSequenceable()) { 453 return; 454 } 455 456 var images = [], 457 base = this.images[0], 458 min = this.images[1], 459 max = this.images[2]; 460 461 do { 462 images.push(base.replace(/\.\w+$/, min + '$&')); 463 } while (++min <= max); 464 465 this.images = images; 466 }, 467 468 /** 469 * Preload an images 470 */ 471 preload: function() { 472 var path, 473 length = this.images.length, 474 i = 0; 475 476 for (; i < length; i++) { 477 path = this.images[i]; 478 if (!loadedImages[path]) { 479 loadedImages[path] = new Image(); 480 loadedImages[path].src = path; 481 } 482 } 483 }, 484 485 /** 486 * Shuffle an images 487 */ 488 shuffle: function() { 489 var j, t, 490 i = this.images.length, 491 original = this.images.join(); 492 493 if (!i) { 494 return; 495 } 496 497 while (i) { 498 j = Math.floor(Math.random() * i); 499 t = this.images[--i]; 500 this.images[i] = this.images[j]; 501 this.images[j] = t; 502 } 503 504 if (this.images.join() === original) { 505 this.shuffle(); 506 } 507 }, 508 509 /** 510 * Get the image from index 511 * 512 * @param {number} index 513 * @returns {string} 514 */ 515 get: function(index) { 516 return this.images[index]; 517 }, 518 519 /** 520 * Get the URL with function of CSS 521 * 522 * @param {number} index 523 * @returns {string} 524 */ 525 url: function(index) { 526 return 'url(' + this.get(index) + ')'; 527 }, 528 529 /** 530 * Count of images 531 * 532 * @returns {number} 533 */ 534 count: function() { 535 return this.images.length; 536 } 537 }); 538 539 $.BgSwitcher = BgSwitcher; 540}(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.