@@ 374-649 (lines=276) @@ | ||
371 | ||
372 | angular.module('ui.bootstrap.carousel', []) |
|
373 | ||
374 | .controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) { |
|
375 | var self = this, |
|
376 | slides = self.slides = $scope.slides = [], |
|
377 | SLIDE_DIRECTION = 'uib-slideDirection', |
|
378 | currentIndex = $scope.active, |
|
379 | currentInterval, isPlaying, bufferedTransitions = []; |
|
380 | ||
381 | var destroyed = false; |
|
382 | ||
383 | self.addSlide = function(slide, element) { |
|
384 | slides.push({ |
|
385 | slide: slide, |
|
386 | element: element |
|
387 | }); |
|
388 | slides.sort(function(a, b) { |
|
389 | return +a.slide.index - +b.slide.index; |
|
390 | }); |
|
391 | //if this is the first slide or the slide is set to active, select it |
|
392 | if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) { |
|
393 | if ($scope.$currentTransition) { |
|
394 | $scope.$currentTransition = null; |
|
395 | } |
|
396 | ||
397 | currentIndex = slide.index; |
|
398 | $scope.active = slide.index; |
|
399 | setActive(currentIndex); |
|
400 | self.select(slides[findSlideIndex(slide)]); |
|
401 | if (slides.length === 1) { |
|
402 | $scope.play(); |
|
403 | } |
|
404 | } |
|
405 | }; |
|
406 | ||
407 | self.getCurrentIndex = function() { |
|
408 | for (var i = 0; i < slides.length; i++) { |
|
409 | if (slides[i].slide.index === currentIndex) { |
|
410 | return i; |
|
411 | } |
|
412 | } |
|
413 | }; |
|
414 | ||
415 | self.next = $scope.next = function() { |
|
416 | var newIndex = (self.getCurrentIndex() + 1) % slides.length; |
|
417 | ||
418 | if (newIndex === 0 && $scope.noWrap()) { |
|
419 | $scope.pause(); |
|
420 | return; |
|
421 | } |
|
422 | ||
423 | return self.select(slides[newIndex], 'next'); |
|
424 | }; |
|
425 | ||
426 | self.prev = $scope.prev = function() { |
|
427 | var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; |
|
428 | ||
429 | if ($scope.noWrap() && newIndex === slides.length - 1) { |
|
430 | $scope.pause(); |
|
431 | return; |
|
432 | } |
|
433 | ||
434 | return self.select(slides[newIndex], 'prev'); |
|
435 | }; |
|
436 | ||
437 | self.removeSlide = function(slide) { |
|
438 | var index = findSlideIndex(slide); |
|
439 | ||
440 | var bufferedIndex = bufferedTransitions.indexOf(slides[index]); |
|
441 | if (bufferedIndex !== -1) { |
|
442 | bufferedTransitions.splice(bufferedIndex, 1); |
|
443 | } |
|
444 | ||
445 | //get the index of the slide inside the carousel |
|
446 | slides.splice(index, 1); |
|
447 | if (slides.length > 0 && currentIndex === index) { |
|
448 | if (index >= slides.length) { |
|
449 | currentIndex = slides.length - 1; |
|
450 | $scope.active = currentIndex; |
|
451 | setActive(currentIndex); |
|
452 | self.select(slides[slides.length - 1]); |
|
453 | } else { |
|
454 | currentIndex = index; |
|
455 | $scope.active = currentIndex; |
|
456 | setActive(currentIndex); |
|
457 | self.select(slides[index]); |
|
458 | } |
|
459 | } else if (currentIndex > index) { |
|
460 | currentIndex--; |
|
461 | $scope.active = currentIndex; |
|
462 | } |
|
463 | ||
464 | //clean the active value when no more slide |
|
465 | if (slides.length === 0) { |
|
466 | currentIndex = null; |
|
467 | $scope.active = null; |
|
468 | clearBufferedTransitions(); |
|
469 | } |
|
470 | }; |
|
471 | ||
472 | /* direction: "prev" or "next" */ |
|
473 | self.select = $scope.select = function(nextSlide, direction) { |
|
474 | var nextIndex = findSlideIndex(nextSlide.slide); |
|
475 | //Decide direction if it's not given |
|
476 | if (direction === undefined) { |
|
477 | direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; |
|
478 | } |
|
479 | //Prevent this user-triggered transition from occurring if there is already one in progress |
|
480 | if (nextSlide.slide.index !== currentIndex && |
|
481 | !$scope.$currentTransition) { |
|
482 | goNext(nextSlide.slide, nextIndex, direction); |
|
483 | } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) { |
|
484 | bufferedTransitions.push(slides[nextIndex]); |
|
485 | } |
|
486 | }; |
|
487 | ||
488 | /* Allow outside people to call indexOf on slides array */ |
|
489 | $scope.indexOfSlide = function(slide) { |
|
490 | return +slide.slide.index; |
|
491 | }; |
|
492 | ||
493 | $scope.isActive = function(slide) { |
|
494 | return $scope.active === slide.slide.index; |
|
495 | }; |
|
496 | ||
497 | $scope.isPrevDisabled = function() { |
|
498 | return $scope.active === 0 && $scope.noWrap(); |
|
499 | }; |
|
500 | ||
501 | $scope.isNextDisabled = function() { |
|
502 | return $scope.active === slides.length - 1 && $scope.noWrap(); |
|
503 | }; |
|
504 | ||
505 | $scope.pause = function() { |
|
506 | if (!$scope.noPause) { |
|
507 | isPlaying = false; |
|
508 | resetTimer(); |
|
509 | } |
|
510 | }; |
|
511 | ||
512 | $scope.play = function() { |
|
513 | if (!isPlaying) { |
|
514 | isPlaying = true; |
|
515 | restartTimer(); |
|
516 | } |
|
517 | }; |
|
518 | ||
519 | $scope.$on('$destroy', function() { |
|
520 | destroyed = true; |
|
521 | resetTimer(); |
|
522 | }); |
|
523 | ||
524 | $scope.$watch('noTransition', function(noTransition) { |
|
525 | $animate.enabled($element, !noTransition); |
|
526 | }); |
|
527 | ||
528 | $scope.$watch('interval', restartTimer); |
|
529 | ||
530 | $scope.$watchCollection('slides', resetTransition); |
|
531 | ||
532 | $scope.$watch('active', function(index) { |
|
533 | if (angular.isNumber(index) && currentIndex !== index) { |
|
534 | for (var i = 0; i < slides.length; i++) { |
|
535 | if (slides[i].slide.index === index) { |
|
536 | index = i; |
|
537 | break; |
|
538 | } |
|
539 | } |
|
540 | ||
541 | var slide = slides[index]; |
|
542 | if (slide) { |
|
543 | setActive(index); |
|
544 | self.select(slides[index]); |
|
545 | currentIndex = index; |
|
546 | } |
|
547 | } |
|
548 | }); |
|
549 | ||
550 | function clearBufferedTransitions() { |
|
551 | while (bufferedTransitions.length) { |
|
552 | bufferedTransitions.shift(); |
|
553 | } |
|
554 | } |
|
555 | ||
556 | function getSlideByIndex(index) { |
|
557 | for (var i = 0, l = slides.length; i < l; ++i) { |
|
558 | if (slides[i].index === index) { |
|
559 | return slides[i]; |
|
560 | } |
|
561 | } |
|
562 | } |
|
563 | ||
564 | function setActive(index) { |
|
565 | for (var i = 0; i < slides.length; i++) { |
|
566 | slides[i].slide.active = i === index; |
|
567 | } |
|
568 | } |
|
569 | ||
570 | function goNext(slide, index, direction) { |
|
571 | if (destroyed) { |
|
572 | return; |
|
573 | } |
|
574 | ||
575 | angular.extend(slide, {direction: direction}); |
|
576 | angular.extend(slides[currentIndex].slide || {}, {direction: direction}); |
|
577 | if ($animate.enabled($element) && !$scope.$currentTransition && |
|
578 | slides[index].element && self.slides.length > 1) { |
|
579 | slides[index].element.data(SLIDE_DIRECTION, slide.direction); |
|
580 | var currentIdx = self.getCurrentIndex(); |
|
581 | ||
582 | if (angular.isNumber(currentIdx) && slides[currentIdx].element) { |
|
583 | slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction); |
|
584 | } |
|
585 | ||
586 | $scope.$currentTransition = true; |
|
587 | $animate.on('addClass', slides[index].element, function(element, phase) { |
|
588 | if (phase === 'close') { |
|
589 | $scope.$currentTransition = null; |
|
590 | $animate.off('addClass', element); |
|
591 | if (bufferedTransitions.length) { |
|
592 | var nextSlide = bufferedTransitions.pop().slide; |
|
593 | var nextIndex = nextSlide.index; |
|
594 | var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; |
|
595 | clearBufferedTransitions(); |
|
596 | ||
597 | goNext(nextSlide, nextIndex, nextDirection); |
|
598 | } |
|
599 | } |
|
600 | }); |
|
601 | } |
|
602 | ||
603 | $scope.active = slide.index; |
|
604 | currentIndex = slide.index; |
|
605 | setActive(index); |
|
606 | ||
607 | //every time you change slides, reset the timer |
|
608 | restartTimer(); |
|
609 | } |
|
610 | ||
611 | function findSlideIndex(slide) { |
|
612 | for (var i = 0; i < slides.length; i++) { |
|
613 | if (slides[i].slide === slide) { |
|
614 | return i; |
|
615 | } |
|
616 | } |
|
617 | } |
|
618 | ||
619 | function resetTimer() { |
|
620 | if (currentInterval) { |
|
621 | $interval.cancel(currentInterval); |
|
622 | currentInterval = null; |
|
623 | } |
|
624 | } |
|
625 | ||
626 | function resetTransition(slides) { |
|
627 | if (!slides.length) { |
|
628 | $scope.$currentTransition = null; |
|
629 | clearBufferedTransitions(); |
|
630 | } |
|
631 | } |
|
632 | ||
633 | function restartTimer() { |
|
634 | resetTimer(); |
|
635 | var interval = +$scope.interval; |
|
636 | if (!isNaN(interval) && interval > 0) { |
|
637 | currentInterval = $interval(timerFn, interval); |
|
638 | } |
|
639 | } |
|
640 | ||
641 | function timerFn() { |
|
642 | var interval = +$scope.interval; |
|
643 | if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { |
|
644 | $scope.next(); |
|
645 | } else { |
|
646 | $scope.pause(); |
|
647 | } |
|
648 | } |
|
649 | }]) |
|
650 | ||
651 | .directive('uibCarousel', function() { |
|
652 | return { |
@@ 373-648 (lines=276) @@ | ||
370 | ||
371 | angular.module('ui.bootstrap.carousel', []) |
|
372 | ||
373 | .controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) { |
|
374 | var self = this, |
|
375 | slides = self.slides = $scope.slides = [], |
|
376 | SLIDE_DIRECTION = 'uib-slideDirection', |
|
377 | currentIndex = $scope.active, |
|
378 | currentInterval, isPlaying, bufferedTransitions = []; |
|
379 | ||
380 | var destroyed = false; |
|
381 | ||
382 | self.addSlide = function(slide, element) { |
|
383 | slides.push({ |
|
384 | slide: slide, |
|
385 | element: element |
|
386 | }); |
|
387 | slides.sort(function(a, b) { |
|
388 | return +a.slide.index - +b.slide.index; |
|
389 | }); |
|
390 | //if this is the first slide or the slide is set to active, select it |
|
391 | if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) { |
|
392 | if ($scope.$currentTransition) { |
|
393 | $scope.$currentTransition = null; |
|
394 | } |
|
395 | ||
396 | currentIndex = slide.index; |
|
397 | $scope.active = slide.index; |
|
398 | setActive(currentIndex); |
|
399 | self.select(slides[findSlideIndex(slide)]); |
|
400 | if (slides.length === 1) { |
|
401 | $scope.play(); |
|
402 | } |
|
403 | } |
|
404 | }; |
|
405 | ||
406 | self.getCurrentIndex = function() { |
|
407 | for (var i = 0; i < slides.length; i++) { |
|
408 | if (slides[i].slide.index === currentIndex) { |
|
409 | return i; |
|
410 | } |
|
411 | } |
|
412 | }; |
|
413 | ||
414 | self.next = $scope.next = function() { |
|
415 | var newIndex = (self.getCurrentIndex() + 1) % slides.length; |
|
416 | ||
417 | if (newIndex === 0 && $scope.noWrap()) { |
|
418 | $scope.pause(); |
|
419 | return; |
|
420 | } |
|
421 | ||
422 | return self.select(slides[newIndex], 'next'); |
|
423 | }; |
|
424 | ||
425 | self.prev = $scope.prev = function() { |
|
426 | var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; |
|
427 | ||
428 | if ($scope.noWrap() && newIndex === slides.length - 1) { |
|
429 | $scope.pause(); |
|
430 | return; |
|
431 | } |
|
432 | ||
433 | return self.select(slides[newIndex], 'prev'); |
|
434 | }; |
|
435 | ||
436 | self.removeSlide = function(slide) { |
|
437 | var index = findSlideIndex(slide); |
|
438 | ||
439 | var bufferedIndex = bufferedTransitions.indexOf(slides[index]); |
|
440 | if (bufferedIndex !== -1) { |
|
441 | bufferedTransitions.splice(bufferedIndex, 1); |
|
442 | } |
|
443 | ||
444 | //get the index of the slide inside the carousel |
|
445 | slides.splice(index, 1); |
|
446 | if (slides.length > 0 && currentIndex === index) { |
|
447 | if (index >= slides.length) { |
|
448 | currentIndex = slides.length - 1; |
|
449 | $scope.active = currentIndex; |
|
450 | setActive(currentIndex); |
|
451 | self.select(slides[slides.length - 1]); |
|
452 | } else { |
|
453 | currentIndex = index; |
|
454 | $scope.active = currentIndex; |
|
455 | setActive(currentIndex); |
|
456 | self.select(slides[index]); |
|
457 | } |
|
458 | } else if (currentIndex > index) { |
|
459 | currentIndex--; |
|
460 | $scope.active = currentIndex; |
|
461 | } |
|
462 | ||
463 | //clean the active value when no more slide |
|
464 | if (slides.length === 0) { |
|
465 | currentIndex = null; |
|
466 | $scope.active = null; |
|
467 | clearBufferedTransitions(); |
|
468 | } |
|
469 | }; |
|
470 | ||
471 | /* direction: "prev" or "next" */ |
|
472 | self.select = $scope.select = function(nextSlide, direction) { |
|
473 | var nextIndex = findSlideIndex(nextSlide.slide); |
|
474 | //Decide direction if it's not given |
|
475 | if (direction === undefined) { |
|
476 | direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; |
|
477 | } |
|
478 | //Prevent this user-triggered transition from occurring if there is already one in progress |
|
479 | if (nextSlide.slide.index !== currentIndex && |
|
480 | !$scope.$currentTransition) { |
|
481 | goNext(nextSlide.slide, nextIndex, direction); |
|
482 | } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) { |
|
483 | bufferedTransitions.push(slides[nextIndex]); |
|
484 | } |
|
485 | }; |
|
486 | ||
487 | /* Allow outside people to call indexOf on slides array */ |
|
488 | $scope.indexOfSlide = function(slide) { |
|
489 | return +slide.slide.index; |
|
490 | }; |
|
491 | ||
492 | $scope.isActive = function(slide) { |
|
493 | return $scope.active === slide.slide.index; |
|
494 | }; |
|
495 | ||
496 | $scope.isPrevDisabled = function() { |
|
497 | return $scope.active === 0 && $scope.noWrap(); |
|
498 | }; |
|
499 | ||
500 | $scope.isNextDisabled = function() { |
|
501 | return $scope.active === slides.length - 1 && $scope.noWrap(); |
|
502 | }; |
|
503 | ||
504 | $scope.pause = function() { |
|
505 | if (!$scope.noPause) { |
|
506 | isPlaying = false; |
|
507 | resetTimer(); |
|
508 | } |
|
509 | }; |
|
510 | ||
511 | $scope.play = function() { |
|
512 | if (!isPlaying) { |
|
513 | isPlaying = true; |
|
514 | restartTimer(); |
|
515 | } |
|
516 | }; |
|
517 | ||
518 | $scope.$on('$destroy', function() { |
|
519 | destroyed = true; |
|
520 | resetTimer(); |
|
521 | }); |
|
522 | ||
523 | $scope.$watch('noTransition', function(noTransition) { |
|
524 | $animate.enabled($element, !noTransition); |
|
525 | }); |
|
526 | ||
527 | $scope.$watch('interval', restartTimer); |
|
528 | ||
529 | $scope.$watchCollection('slides', resetTransition); |
|
530 | ||
531 | $scope.$watch('active', function(index) { |
|
532 | if (angular.isNumber(index) && currentIndex !== index) { |
|
533 | for (var i = 0; i < slides.length; i++) { |
|
534 | if (slides[i].slide.index === index) { |
|
535 | index = i; |
|
536 | break; |
|
537 | } |
|
538 | } |
|
539 | ||
540 | var slide = slides[index]; |
|
541 | if (slide) { |
|
542 | setActive(index); |
|
543 | self.select(slides[index]); |
|
544 | currentIndex = index; |
|
545 | } |
|
546 | } |
|
547 | }); |
|
548 | ||
549 | function clearBufferedTransitions() { |
|
550 | while (bufferedTransitions.length) { |
|
551 | bufferedTransitions.shift(); |
|
552 | } |
|
553 | } |
|
554 | ||
555 | function getSlideByIndex(index) { |
|
556 | for (var i = 0, l = slides.length; i < l; ++i) { |
|
557 | if (slides[i].index === index) { |
|
558 | return slides[i]; |
|
559 | } |
|
560 | } |
|
561 | } |
|
562 | ||
563 | function setActive(index) { |
|
564 | for (var i = 0; i < slides.length; i++) { |
|
565 | slides[i].slide.active = i === index; |
|
566 | } |
|
567 | } |
|
568 | ||
569 | function goNext(slide, index, direction) { |
|
570 | if (destroyed) { |
|
571 | return; |
|
572 | } |
|
573 | ||
574 | angular.extend(slide, {direction: direction}); |
|
575 | angular.extend(slides[currentIndex].slide || {}, {direction: direction}); |
|
576 | if ($animate.enabled($element) && !$scope.$currentTransition && |
|
577 | slides[index].element && self.slides.length > 1) { |
|
578 | slides[index].element.data(SLIDE_DIRECTION, slide.direction); |
|
579 | var currentIdx = self.getCurrentIndex(); |
|
580 | ||
581 | if (angular.isNumber(currentIdx) && slides[currentIdx].element) { |
|
582 | slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction); |
|
583 | } |
|
584 | ||
585 | $scope.$currentTransition = true; |
|
586 | $animate.on('addClass', slides[index].element, function(element, phase) { |
|
587 | if (phase === 'close') { |
|
588 | $scope.$currentTransition = null; |
|
589 | $animate.off('addClass', element); |
|
590 | if (bufferedTransitions.length) { |
|
591 | var nextSlide = bufferedTransitions.pop().slide; |
|
592 | var nextIndex = nextSlide.index; |
|
593 | var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; |
|
594 | clearBufferedTransitions(); |
|
595 | ||
596 | goNext(nextSlide, nextIndex, nextDirection); |
|
597 | } |
|
598 | } |
|
599 | }); |
|
600 | } |
|
601 | ||
602 | $scope.active = slide.index; |
|
603 | currentIndex = slide.index; |
|
604 | setActive(index); |
|
605 | ||
606 | //every time you change slides, reset the timer |
|
607 | restartTimer(); |
|
608 | } |
|
609 | ||
610 | function findSlideIndex(slide) { |
|
611 | for (var i = 0; i < slides.length; i++) { |
|
612 | if (slides[i].slide === slide) { |
|
613 | return i; |
|
614 | } |
|
615 | } |
|
616 | } |
|
617 | ||
618 | function resetTimer() { |
|
619 | if (currentInterval) { |
|
620 | $interval.cancel(currentInterval); |
|
621 | currentInterval = null; |
|
622 | } |
|
623 | } |
|
624 | ||
625 | function resetTransition(slides) { |
|
626 | if (!slides.length) { |
|
627 | $scope.$currentTransition = null; |
|
628 | clearBufferedTransitions(); |
|
629 | } |
|
630 | } |
|
631 | ||
632 | function restartTimer() { |
|
633 | resetTimer(); |
|
634 | var interval = +$scope.interval; |
|
635 | if (!isNaN(interval) && interval > 0) { |
|
636 | currentInterval = $interval(timerFn, interval); |
|
637 | } |
|
638 | } |
|
639 | ||
640 | function timerFn() { |
|
641 | var interval = +$scope.interval; |
|
642 | if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { |
|
643 | $scope.next(); |
|
644 | } else { |
|
645 | $scope.pause(); |
|
646 | } |
|
647 | } |
|
648 | }]) |
|
649 | ||
650 | .directive('uibCarousel', function() { |
|
651 | return { |