1/* 2--- 3 4script: NivooSlider.js 5 6description: A nice image slider for MooTools. 7 8license: MIT-style license 9 10authors: 11- Johannes Fischer 12 13requires: 14- core/1.3: '*' 15 16provides: 17- NivooSlider 18 19... 20 */ 21 22var NivooSlider = new Class({ 23 24 Implements: [Events, Options], 25 26 caption: null, 27 children: null, 28 containerSize: 0, 29 count: 4, 30 currentSlide: 0, 31 currentImage: '', 32 effects: { 33 // used for random effects 34 common: ['fade', 'fold'], 35 horizontal: ['sliceLeftUp', 'sliceLeftDown', 'sliceLeftRightDown', 'sliceLeftRightUp', 'sliceRightDown', 'sliceRightUp', 'wipeDown', 'wipeUp'], 36 vertical: ['sliceDownLeft', 'sliceDownRight', 'sliceUpDownLeft', 'sliceUpDownRight', 'sliceUpLeft', 'sliceUpRight', 'wipeLeft', 'wipeRight'] 37 }, 38 holder: null, 39 hover: false, 40 interval: null, 41 orientation: '', 42 paused: false, 43 running: false, 44 slices: null, 45 sliceSize: null, 46 totalSlides: 0, 47 48 options: { 49 animSpeed: 500, 50 autoPlay: true, 51 directionNav: true, 52 directionNavHide: true, 53 directionNavWidth: '40px', 54 effect: 'sliceDown', // TODO allow to pass an array with multiple effects 55 interval: 3000, 56 orientation: 'vertical', 57 pauseOnHover: true, 58 slices: 15, 59 60 // not implemented yet 61 directionNavPosition: 'inside|outside', 62 preLoadImages: false 63 64 //onFinish: function () {} 65 //onLastSlide: function () {} 66 //onStart: function () {} 67 }, 68 69 initialize: function (container, options) 70 { 71 this.container = $(container); 72 73 this.setOptions(options); 74 this.orientation = this.options.orientation; 75 76 this.effects.horizontal.combine(this.effects.common); 77 this.effects.vertical.combine(this.effects.common); 78 79 this.initSlider(); 80 this.createSlices(); 81 if (this.options.autoPlay) 82 { 83 this.play(); 84 } 85 }, 86 87 animate: function (slice, fxStyles, last) 88 { 89 var fx = slice.retrieve('fxInstance'), 90 isLast = last !== undefined && last === true; 91 92 fx.start(fxStyles).chain(function () { 93 this.count += 1; 94 if (this.count === this.options.slices || isLast) 95 { 96 this.running = false; 97 98 // fire onFinish function 99 this.finish(); 100 101 this.setBackgroundImage(); 102 103 this.count = 0; 104 105 if (this.currentSlide === (this.totalSlides - 1)) 106 { 107 this.lastSlide(); 108 } 109 } 110 }.bind(this)); 111 }, 112 113 arrangeSlices: function (orientation) 114 { 115 var height, 116 position, 117 sliceSize, 118 width; 119 120 this.slices.each(function (el, i) { 121 122 position = { 123 left: orientation === 'vertical' ? this.sliceSize.x * i : 0, 124 top: orientation === 'horizontal' ? this.sliceSize.y * i : 0 125 }; 126 127 // set size & position 128 if (orientation === 'horizontal') 129 { 130 height = i === this.options.slices - 1 ? this.containerSize.y - (this.sliceSize.y * i) : this.sliceSize.y; 131 width = '100%'; 132 133 el.setStyles({ 134 height: height, 135 top: position.top, 136 width: width 137 }); 138 } 139 // if vertical 140 else 141 { 142 height = 0; 143 width = i === this.options.slices - 1 ? this.containerSize.x - (this.sliceSize.x * i) : this.sliceSize.x; 144 145 el.setStyles({ 146 height: height, 147 left: position.left, 148 top: '', 149 width: width 150 }); 151 } 152 153 el.store('fxInstance', new Fx.Morph(el, { 154 duration: this.options.animSpeed 155 })).store('coordinates', Object.merge(position, {height: height, width: width})); 156 }, this); 157 }, 158 159 createCaption: function () 160 { 161 this.caption = new Element('p', { 162 styles: { 163 opacity: 0 164 } 165 }).inject(this.holder); 166 167 this.caption.store('fxInstance', new Fx.Morph(this.caption, { 168 duration: 200, 169 wait: false 170 })); 171 }, 172 173 createDirectionNav: function () 174 { 175 var directionNavStyles, 176 leftContainer, 177 rightContainer, 178 width; 179 180 width = this.options.directionNavWidth; 181 182 directionNavStyles = { 183 height: this.containerSize.y, 184 width: width 185 }; 186 187 // create container 188 leftContainer = new Element('div.direction-nav-left', { 189 styles: directionNavStyles 190 }).inject(this.holder); 191 192 rightContainer = new Element('div.direction-nav-right', { 193 styles: directionNavStyles 194 }).inject(this.holder); 195 196 // create controls 197 198 this.leftNav = new Element('a', { 199 events: { 200 'click': function (e) { 201 e.stop(); 202 if (this.options.autoPlay) 203 { 204 this.pause(); 205 if (!this.options.pauseOnHover) 206 { 207 this.play(); 208 } 209 } 210 this.previous(); 211 }.bind(this) 212 }, 213 href: '#', 214 styles: { 215 height: directionNavStyles.height 216 } 217 }).inject(leftContainer); 218 219 this.rightNav = new Element('a', { 220 events: { 221 'click': function (e) { 222 e.stop(); 223 if (this.options.autoPlay) 224 { 225 this.pause(); 226 if (!this.options.pauseOnHover) 227 { 228 this.play(); 229 } 230 } 231 this.next(); 232 }.bind(this) 233 }, 234 href: '#', 235 styles: { 236 height: directionNavStyles.height 237 } 238 }).inject(rightContainer); 239 240 if (this.options.directionNavHide && this.options.directionNav) 241 { 242 $$(this.leftNav, this.rightNav).setStyle('opacity', 0); 243 this.holder.addEvents({ 244 'mouseout': function () { 245 $$(this.leftNav, this.rightNav).fade(0); 246 }.bind(this), 247 'mouseover': function () { 248 $$(this.leftNav, this.rightNav).fade(1); 249 }.bind(this) 250 }); 251 } 252 }, 253 254 createLinkHolder: function () 255 { 256 this.linkHolder = new Element('a.nivoo-link', { 257 href: '#' 258 }).inject(this.holder); 259 }, 260 261 createSlices: function () 262 { 263 this.sliceSize = {
264 x: (this.containerSize.x / this.options.slices).round(), 265 y: (this.containerSize.y / this.options.slices).round() 266 }; 267 268 // effects that need one slice only 269 if (['fade', 'wipeLeft', 'wipeRight'].contains(this.options.effect)) 270 { 271 this.options.slices = 1; 272 } 273 274 this.options.slices.each(function (i) { 275 new Element('div.nivoo-slice').inject(this.holder); 276 }, this); 277 278 this.slices = this.getSlices(); 279 280 this.arrangeSlices(this.options.orientation); 281 }, 282 283 getImages: function () 284 { 285 return this.holder.getElements('img'); 286 }, 287 288 getSlices: function () 289 { 290 return this.holder.getElements('.nivoo-slice'); 291 }, 292 293 initSlider: function () 294 { 295 // wrap child elements 296 this.holder = new Element('div.nivoo-slider-holder').adopt(this.container.getChildren()).inject(this.container); 297 298 this.containerSize = this.holder.getSize(); 299 300 // Find our slider children 301 this.children = this.getImages(); 302 303 this.totalSlides = this.children.length; 304 305 this.children.setStyle('display', 'none'); 306 307 this.currentImage = this.children[0]; 308 309 // init LinkHolderand set link 310 this.createLinkHolder(); 311 this.setLink(); 312 313 // Set first background 314 this.holder.setStyle('background-image', 'url(' + this.currentImage.get('src') + ')'); 315 316 this.createCaption(); 317 318 this.showCaption(); 319 320 // attach pauseOnHover 321 if (this.options.pauseOnHover && this.options.autoPlay) 322 { 323 this.holder.addEvents({ 324 'mouseenter': function () { 325 this.pause(); 326 }.bind(this), 327 'mouseleave': function () { 328 this.play(); 329 }.bind(this) 330 }); 331 } 332 333 // create directional navigation 334 if (this.options.directionNav) 335 { 336 this.createDirectionNav(); 337 } 338 }, 339 340 hideCaption: function () 341 { 342 this.caption.retrieve('fxInstance').start({ 343 bottom: this.caption.getHeight() * -1, 344 opacity: 0.5 345 }); 346 }, 347 348 next: function () 349 { 350 this.currentSlide += 1; 351 352 if (this.currentSlide === this.totalSlides) 353 { 354 this.currentSlide = 0; 355 } 356 357 this.slide(); 358 }, 359 360 pause: function () 361 { 362 window.clearInterval(this.interval); 363 }, 364 365 play: function () 366 { 367 this.interval = this.next.periodical(this.options.interval, this); 368 }, 369 370 previous: function () 371 { 372 if (this.options.autoPlay) 373 { 374 this.pause(); 375 if (!this.options.pauseOnHover) 376 { 377 this.play(); 378 } 379 } 380 381 this.currentSlide -= 1; 382 383 if (this.currentSlide < 0) 384 { 385 this.currentSlide = (this.totalSlides - 1); 386 } 387 388 this.slide(); 389 }, 390 391 showCaption: function () 392 { 393 var title = this.currentImage.get('title'); 394 395 if (!title) 396 { 397 this.hideCaption(); 398 return; 399 } 400 401 this.setCaptionText(title); 402 403 this.caption.retrieve('fxInstance').start({ 404 bottom: 0, 405 opacity: 1 406 }); 407 }, 408 409 slide: function (slideNo) 410 { 411 var coordinates, 412 effect, 413 orientation, 414 slice, 415 slices, 416 styles, 417 timeBuff; 418 419 if (this.running) 420 { 421 return; 422 } 423 424 if (this.options.orientation === 'random') 425 { 426 orientation = ['horizontal', 'vertical'].getRandom(); 427 } 428 else 429 { 430 orientation = this.options.orientation; 431 } 432 433 if (orientation !== this.orientation) 434 { 435 this.arrangeSlices(orientation); 436 this.orientation = orientation; 437 } 438 439 if (slideNo !== undefined) 440 { 441 this.currentSlide = slideNo; 442 } 443 444 // Set currentImage 445 this.currentImage = this.children[this.currentSlide]; 446 447 this.setLink(); 448 449 // Process caption 450 this.showCaption(); 451 452 // TODO use this.slices within each loop instead 453 slices = this.slices; 454 timeBuff = 0; 455 456 // reset slices 457 this.slices.each(function (slice) { 458 459 coordinates = slice.retrieve('coordinates'); 460 461 slice.setStyles({ 462 background: 'url(' + this.currentImage.get('src') + ') no-repeat -' + coordinates.left + 'px ' + coordinates.top * -1 + 'px', 463 bottom: '', 464 height: coordinates.height, 465 left: coordinates.left, 466 opacity: 0, 467 right: '', 468 top: coordinates.top, 469 width: coordinates.width 470 }); 471 472 var property = orientation === 'horizontal' ? 'width' : 'height';
473 474 slice.setStyle(property, 0); 475 }, this); 476 477 // fire onStart function 478 this.start(); 479 480 // Run effects 481 this.running = true; 482 483 effect = this.options.effect; 484 485 if (effect === 'random') 486 { 487 effect = this.effects[orientation].getRandom(); 488 } 489 490 // vertical effects 491 if (['sliceDownRight', 'sliceDownLeft'].contains(effect)) 492 { 493 if (effect === 'sliceDownLeft') 494 { 495 slices = slices.reverse(); 496 } 497 498 slices.each(function (slice) { 499 slice.setStyle('top', 0); 500 501 this.animate.delay(100 + timeBuff, this, [slice, {height: this.containerSize.y, opacity: 1}]); 502 503 timeBuff += 50; 504 }, this); 505 } 506 else if (['sliceUpRight', 'sliceUpLeft'].contains(effect)) 507 { 508 if (effect === 'sliceUpLeft') 509 { 510 slices = slices.reverse(); 511 } 512 513 slices.each(function (slice) { 514 var fx = slice.retrieve('fxInstance'); 515 516 slice.setStyle('bottom', 0); 517 518 this.animate.delay(100 + timeBuff, this, [slice, {height: this.containerSize.y, opacity: 1}]); 519 520 timeBuff += 50; 521 }, this); 522 } 523 else if (['sliceUpDownRight', 'sliceUpDownLeft'].contains(effect)) 524 { 525 if (effect === 'sliceUpDownLeft') 526 { 527 slices = slices.reverse(); 528 } 529 530 slices.each(function (slice, i) { 531 if (i % 2 === 0) 532 { 533 slice.setStyle('top', 0); 534 } 535 else 536 { 537 slice.setStyles({ 538 bottom: 0, 539 top: '' 540 }); 541 } 542 543 this.animate.delay(100 + timeBuff, this, [slice, {height: this.containerSize.y, opacity: 1}]); 544 545 timeBuff += 50; 546 }, this); 547 } 548 else if (['wipeLeft', 'wipeRight'].contains(effect)) 549 { 550 styles = { 551 height: this.containerSize.y, 552 opacity: 1, 553 width: 0 554 }; 555 556 if (effect === 'wipeRight') 557 { 558 Object.append(styles, { 559 backgroundPosition: 'top right', 560 left: '', 561 right: 0 562 }); 563 } 564 565 slice = slices[0]; 566 567 slice.setStyles(styles); 568 this.animate(slice, {width: this.containerSize.x}, true); 569 } 570 571 // horizontal effects 572 else if (['sliceLeftUp', 'sliceLeftDown', 'sliceRightDown', 'sliceRightUp'].contains(effect)) 573 { 574 if (effect === 'sliceLeftUp' || effect === 'sliceRightUp') 575 { 576 slices = slices.reverse(); 577 } 578 579 if (effect === 'sliceRightDown' || effect === 'sliceRightUp') 580 { 581 slices.setStyles({ 582 left: '', 583 right: 0 584 }); 585 } 586 else 587 { 588 slices.setStyles({ 589 left: 0, 590 right: '' 591 }); 592 } 593 594 slices.each(function (slice) { 595 this.animate.delay(100 + timeBuff, this, [slice, {opacity: 1, width: this.containerSize.x}]); 596 597 timeBuff += 50; 598 }, this); 599 } 600 else if (['sliceLeftRightDown', 'sliceLeftRightUp'].contains(effect)) 601 { 602 if (effect === 'sliceLeftRightUp') 603 { 604 slices = slices.reverse(); 605 } 606 607 slices.each(function (slice, i) { 608 if (i % 2 === 0) 609 { 610 slice.setStyles({ 611 left: 0, 612 right: '' 613 }); 614 } 615 else 616 { 617 slice.setStyles({ 618 left: '', 619 right: 0 620 }); 621 } 622 623 this.animate.delay(100 + timeBuff, this, [slice, {opacity: 1, width: this.containerSize.x}]); 624 625 timeBuff += 50; 626 }, this); 627 } 628 else if (['wipeDown', 'wipeUp'].contains(effect)) 629 { 630 styles = { 631 height: 0, 632 opacity: 1, 633 width: this.containerSize.x 634 }; 635 636 if (effect === 'wipeUp') 637 { 638 Object.append(styles, { 639 backgroundPosition: 'bottom left', 640 bottom: 0, 641 top: '' 642 }); 643 } 644 645 slice = slices[0]; 646 647 slice.setStyles(styles); 648 this.animate(slice, {height: this.containerSize.y}, true); 649 } 650 651 // horizontal or vertical 652 else if (effect === 'fold') 653 { 654 slices.each(function (slice) { 655 var fxStyles = { 656 opacity: 1 657 }; 658 659 if (orientation === 'horizontal') 660 { 661 fxStyles.height = slice.getHeight(); 662 663 slice.setStyles({ 664 height: 0, 665 width: this.containerSize.x 666 }); 667 } 668 else 669 { 670 fxStyles.width = slice.getWidth(); 671 672 slice.setStyles({ 673 height: this.containerSize.y, 674 top: 0, 675 width: 0 676 }); 677 } 678 679 this.animate.delay(100 + timeBuff, this, [slice, fxStyles]); 680 timeBuff += 50; 681 }, this); 682 } 683 else // if (effect == 'fade') 684 { 685 slice = slices[0]; 686 687 slice.setStyles({ 688 height: this.containerSize.y, 689 width: this.containerSize.x 690 }); 691 692 this.animate(slice, {opacity: 1}, true); 693 } 694 }, 695
696 setBackgroundImage: function () 697 { 698 this.holder.setStyle('background-image', 'url(' + this.currentImage.get('src') + ')'); 699 }, 700 701 setCaptionText: function (text) 702 { 703 this.caption.set('text', text); 704 }, 705 706 setLink: function () 707 { 708 //Set active link 709 var clone, 710 imageParent = this.currentImage.getParent(); 711 712 if (imageParent.get('tag') === 'a') 713 { 714 clone = imageParent.clone(false).cloneEvents(imageParent); 715 clone.replaces(this.linkHolder); 716 this.linkHolder = clone; 717 this.linkHolder.addClass('nivoo-link').setStyle('display', 'block'); 718 } 719 else 720 { 721 this.linkHolder.setStyle('display', 'none'); 722 } 723 }, 724 725 /** 726 * Events 727 */ 728 729 finish: function () 730 { 731 this.fireEvent('finish'); 732 }, 733 734 lastSlide: function () 735 { 736 this.fireEvent('lastSlide'); 737 }, 738 739 start: function () 740 { 741 this.fireEvent('start'); 742 } 743 744});
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.