323 |
334 | {this.props.decorators ?
335 | this.props.decorators.map((Decorator, index) => (
336 |
340 |
352 |
353 | )) : null}
354 |
355 |
356 | );
357 | }
358 |
359 | // Touch Events
360 | getTouchEvents() {
361 | let self = this;
362 | if (this.props.swiping === false) {
363 | return null;
364 | }
365 |
366 | return {
367 | onTouchStart(e) {
368 | self.touchObject = {
369 | startX: e.touches[0].pageX,
370 | startY: e.touches[0].pageY,
371 | };
372 | self.handleMouseOver();
373 | },
374 | onTouchMove(e) {
375 | const direction = self.swipeDirection(
376 | self.touchObject.startX,
377 | e.touches[0].pageX,
378 | self.touchObject.startY,
379 | e.touches[0].pageY,
380 | );
381 |
382 | if (direction !== 0) {
383 | e.preventDefault();
384 | }
385 |
386 | const length = self.props.vertical ? Math.round(
387 | Math.sqrt(Math.pow(e.touches[0].pageY - self.touchObject.startY, 2)),
388 | ) : Math.round(
389 | Math.sqrt(Math.pow(e.touches[0].pageX - self.touchObject.startX, 2)),
390 | );
391 |
392 | self.touchObject = {
393 | startX: self.touchObject.startX,
394 | startY: self.touchObject.startY,
395 | endX: e.touches[0].pageX,
396 | endY: e.touches[0].pageY,
397 | length,
398 | direction,
399 | };
400 |
401 | self.setState({
402 | left: self.props.vertical ? 0 : self.getTargetLeft(self.touchObject.length * self.touchObject.direction),
403 | top: self.props.vertical ? self.getTargetLeft(self.touchObject.length * self.touchObject.direction) : 0,
404 | });
405 | },
406 | onTouchEnd(e) {
407 | self.handleSwipe(e);
408 | self.handleMouseOut();
409 | },
410 | onTouchCancel(e) {
411 | self.handleSwipe(e);
412 | },
413 | };
414 | }
415 |
416 | getMouseEvents() {
417 | let self = this;
418 | if (this.props.dragging === false) {
419 | return null;
420 | }
421 |
422 | return {
423 | onMouseOver() {
424 | self.handleMouseOver();
425 | },
426 | onMouseOut() {
427 | self.handleMouseOut();
428 | },
429 | onMouseDown(e) {
430 | self.touchObject = {
431 | startX: e.clientX,
432 | startY: e.clientY,
433 | };
434 |
435 | self.setState({
436 | dragging: true,
437 | });
438 | },
439 | onMouseMove(e) {
440 | if (!self.state.dragging) {
441 | return;
442 | }
443 |
444 | const direction = self.swipeDirection(
445 | self.touchObject.startX,
446 | e.clientX,
447 | self.touchObject.startY,
448 | e.clientY,
449 | );
450 |
451 | if (direction !== 0) {
452 | e.preventDefault();
453 | }
454 |
455 | const length = self.props.vertical ? Math.round(
456 | Math.sqrt(Math.pow(e.clientY - self.touchObject.startY, 2)),
457 | ) : Math.round(
458 | Math.sqrt(Math.pow(e.clientX - self.touchObject.startX, 2)),
459 | );
460 |
461 | self.touchObject = {
462 | startX: self.touchObject.startX,
463 | startY: self.touchObject.startY,
464 | endX: e.clientX,
465 | endY: e.clientY,
466 | length,
467 | direction,
468 | };
469 |
470 | self.setState({
471 | left: self.props.vertical ? 0 : self.getTargetLeft(self.touchObject.length * self.touchObject.direction),
472 | top: self.props.vertical ? self.getTargetLeft(self.touchObject.length * self.touchObject.direction) : 0,
473 | });
474 | },
475 | onMouseUp(e) {
476 | if (!self.state.dragging) {
477 | return;
478 | }
479 |
480 | self.handleSwipe(e);
481 | },
482 | onMouseLeave(e) {
483 | if (!self.state.dragging) {
484 | return;
485 | }
486 |
487 | self.handleSwipe(e);
488 | },
489 | };
490 | }
491 |
492 | handleMouseOver() {
493 | if (this.props.autoplay) {
494 | this.autoplayPaused = true;
495 | this.stopAutoplay();
496 | }
497 | }
498 |
499 | handleMouseOut() {
500 | if (this.props.autoplay && this.autoplayPaused) {
501 | this.startAutoplay();
502 | this.autoplayPaused = null;
503 | }
504 | }
505 |
506 | handleClick = (e) => {
507 | if (this.clickSafe === true) {
508 | e.preventDefault();
509 | e.stopPropagation();
510 |
511 | if (e.nativeEvent) {
512 | e.nativeEvent.stopPropagation();
513 | }
514 | }
515 | }
516 |
517 | handleSwipe(_) {
518 | if (typeof (this.touchObject.length) !== 'undefined' && this.touchObject.length > 44) {
519 | this.clickSafe = true;
520 | } else {
521 | this.clickSafe = false;
522 | }
523 |
524 | let { slidesToShow, slidesToScroll, swipeSpeed } = this.props;
525 | // var slidesToShow = this.props.slidesToShow;
526 | if (slidesToScroll === 'auto') {
527 | slidesToShow = this.state.slidesToScroll;
528 | }
529 | if (React.Children.count(this.props.children) > 1 && this.touchObject.length > (this.state.slideWidth / slidesToShow!) / swipeSpeed!) {
530 | if (this.touchObject.direction === 1) {
531 | if (
532 | this.state.currentSlide >= React.Children.count(this.props.children) - slidesToShow! &&
533 | !this.props.wrapAround
534 | ) {
535 | this.animateSlide(this.props.edgeEasing);
536 | } else {
537 | this.nextSlide();
538 | }
539 | } else if (this.touchObject.direction === -1) {
540 | if (this.state.currentSlide <= 0 && !this.props.wrapAround) {
541 | this.animateSlide(this.props.edgeEasing);
542 | } else {
543 | this.previousSlide();
544 | }
545 | }
546 | } else {
547 | this.goToSlide(this.state.currentSlide);
548 | }
549 |
550 | this.touchObject = {};
551 |
552 | this.setState({
553 | dragging: false,
554 | });
555 | }
556 |
557 | swipeDirection(x1, x2, y1, y2) {
558 | let xDist = x1 - x2;
559 | let yDist = y1 - y2;
560 | let r = Math.atan2(yDist, xDist);
561 | let swipeAngle = Math.round(r * 180 / Math.PI);
562 |
563 | if (swipeAngle < 0) {
564 | swipeAngle = 360 - Math.abs(swipeAngle);
565 | }
566 | if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
567 | return 1;
568 | }
569 | if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
570 | return 1;
571 | }
572 | if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
573 | return -1;
574 | }
575 | if (this.props.vertical === true) {
576 | if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
577 | return 1;
578 | } else {
579 | return -1;
580 | }
581 | }
582 | return 0;
583 |
584 | }
585 |
586 | autoplayIterator = () => {
587 | if (this.props.wrapAround) {
588 | return this.nextSlide();
589 | }
590 | if (this.state.currentSlide !== this.state.slideCount - this.state.slidesToShow) {
591 | this.nextSlide();
592 | } else {
593 | this.stopAutoplay();
594 | }
595 | }
596 |
597 | startAutoplay() {
598 | if (React.Children.count(this.props.children) <= 1) {
599 | return;
600 | }
601 | this.autoplayID = setInterval(this.autoplayIterator, this.props.autoplayInterval);
602 | }
603 |
604 | resetAutoplay() {
605 | if (this.props.resetAutoplay && this.props.autoplay && !this.autoplayPaused) { // by warmhug
606 | this.stopAutoplay();
607 | this.startAutoplay();
608 | }
609 | }
610 |
611 | stopAutoplay() {
612 | if (this.autoplayID) {
613 | clearInterval(this.autoplayID);
614 | }
615 | }
616 |
617 | // Action Methods
618 |
619 | goToSlide = (index) => {
620 | let { beforeSlide, afterSlide } = this.props;
621 | if ((index >= React.Children.count(this.props.children) || index < 0)) {
622 | if (!this.props.wrapAround) { return; };
623 | if (index >= React.Children.count(this.props.children)) {
624 | beforeSlide!(this.state.currentSlide, 0);
625 | return this.setState({
626 | currentSlide: 0,
627 | }, () => {
628 | this.animateSlide(null, null, this.getTargetLeft(null, index), () => {
629 | this.animateSlide(null, 0.01);
630 | afterSlide!(0);
631 | this.resetAutoplay();
632 | this.setExternalData();
633 | });
634 | });
635 | } else {
636 | const endSlide = React.Children.count(this.props.children) - this.state.slidesToScroll;
637 | beforeSlide!(this.state.currentSlide, endSlide);
638 | return this.setState({
639 | currentSlide: endSlide,
640 | }, () => {
641 | this.animateSlide(null, null, this.getTargetLeft(null, index), () => {
642 | this.animateSlide(null, 0.01);
643 | afterSlide!(endSlide);
644 | this.resetAutoplay();
645 | this.setExternalData();
646 | });
647 | });
648 | }
649 | }
650 |
651 | beforeSlide!(this.state.currentSlide, index);
652 |
653 | this.setState({
654 | currentSlide: index,
655 | }, () => {
656 | this.animateSlide();
657 | this.props.afterSlide!(index);
658 | this.resetAutoplay();
659 | this.setExternalData();
660 | });
661 | }
662 |
663 | nextSlide = () => {
664 | const childrenCount = React.Children.count(this.props.children);
665 | let slidesToShow: number = this.props.slidesToShow!;
666 | if (this.props.slidesToScroll === 'auto') {
667 | slidesToShow = this.state.slidesToScroll;
668 | }
669 | if (this.state.currentSlide >= childrenCount - slidesToShow && !this.props.wrapAround) {
670 | return;
671 | }
672 |
673 | if (this.props.wrapAround) {
674 | this.goToSlide(this.state.currentSlide + this.state.slidesToScroll);
675 | } else {
676 | if (this.props.slideWidth !== 1) {
677 | return this.goToSlide(this.state.currentSlide + this.state.slidesToScroll);
678 | }
679 | this.goToSlide(
680 | Math.min(this.state.currentSlide + this.state.slidesToScroll, childrenCount - slidesToShow),
681 | );
682 | }
683 | }
684 |
685 | previousSlide = () => {
686 | if (this.state.currentSlide <= 0 && !this.props.wrapAround) {
687 | return;
688 | }
689 |
690 | if (this.props.wrapAround) {
691 | this.goToSlide(this.state.currentSlide - this.state.slidesToScroll);
692 | } else {
693 | this.goToSlide(Math.max(0, this.state.currentSlide - this.state.slidesToScroll));
694 | }
695 | }
696 |
697 | // Animation
698 |
699 | animateSlide(easing?: any, duration?: any, endValue?: any, callback?: Function) {
700 | this.tweenState(this.props.vertical ? 'top' : 'left', {
701 | easing: easing || this.props.easing,
702 | duration: duration || this.props.speed,
703 | endValue: endValue || this.getTargetLeft(),
704 | delay: null,
705 | beginValue: null,
706 | onEnd: callback || null,
707 | stackBehavior,
708 | });
709 | }
710 |
711 | getTargetLeft(touchOffset?: any, slide?: any) {
712 | let offset;
713 | let target = slide || this.state.currentSlide;
714 | let cellSpacing: number = this.props.cellSpacing!;
715 | switch (this.props.cellAlign) {
716 | case 'left': {
717 | offset = 0;
718 | offset -= cellSpacing * (target);
719 | break;
720 | }
721 | case 'center': {
722 | offset = (this.state.frameWidth - this.state.slideWidth) / 2;
723 | offset -= cellSpacing * (target);
724 | break;
725 | }
726 | case 'right': {
727 | offset = this.state.frameWidth - this.state.slideWidth;
728 | offset -= cellSpacing * (target);
729 | break;
730 | }
731 | default:
732 | break;
733 | }
734 |
735 | let left = this.state.slideWidth * target;
736 |
737 | let lastSlide = this.state.currentSlide > 0 && target + this.state.slidesToScroll >= this.state.slideCount;
738 |
739 | if (lastSlide && this.props.slideWidth !== 1 && !this.props.wrapAround && this.props.slidesToScroll === 'auto') {
740 | left = (this.state.slideWidth * this.state.slideCount) - this.state.frameWidth;
741 | offset = 0;
742 | offset -= cellSpacing * (this.state.slideCount - 1);
743 | }
744 |
745 | offset -= touchOffset || 0;
746 |
747 | return (left - offset) * -1;
748 | }
749 |
750 | // Bootstrapping
751 |
752 | bindEvents() {
753 | if (ExecutionEnvironment.canUseDOM) {
754 | addEvent(window, 'resize', this.onResize);
755 | addEvent(document, 'readystatechange', this.onReadyStateChange);
756 | }
757 | }
758 |
759 | onResize = () => {
760 | this.setDimensions();
761 | }
762 |
763 | onReadyStateChange = () => {
764 | this.setDimensions();
765 | }
766 |
767 | unbindEvents() {
768 | if (ExecutionEnvironment.canUseDOM) {
769 | removeEvent(window, 'resize', this.onResize);
770 | removeEvent(document, 'readystatechange', this.onReadyStateChange);
771 | }
772 | }
773 |
774 | formatChildren(children) {
775 | const positionValue = this.props.vertical ? this.getTweeningValue('top') : this.getTweeningValue('left');
776 | return React.Children.map(children, (child, index) => {
777 | return