home *** CD-ROM | disk | FTP | other *** search
/ Orthodox Religion Class (2nd Semester) / ReligieCls1Sem2.iso / js / lib / jquery.bookblock.js < prev    next >
Encoding:
JavaScript  |  2014-06-29  |  16.3 KB  |  530 lines

  1. /**
  2.  * jquery.bookblock.js v2.0.1
  3.  * http://www.codrops.com
  4.  *
  5.  * Licensed under the MIT license.
  6.  * http://www.opensource.org/licenses/mit-license.php
  7.  * 
  8.  * Copyright 2013, Codrops
  9.  * http://www.codrops.com
  10.  */
  11. ;( function( $, window, undefined ) {
  12.  
  13.     'use strict';
  14.  
  15.     // global
  16.     var $window = $(window),
  17.         Modernizr = window.Modernizr;
  18.  
  19.     // https://gist.github.com/edankwan/4389601
  20.     Modernizr.addTest('csstransformspreserve3d', function () {
  21.         var prop = Modernizr.prefixed('transformStyle');
  22.         var val = 'preserve-3d';
  23.         var computedStyle;
  24.         if(!prop) return false;
  25.  
  26.         prop = prop.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
  27.  
  28.         Modernizr.testStyles('#modernizr{' + prop + ':' + val + ';}', function (el, rule) {
  29.             computedStyle = window.getComputedStyle ? getComputedStyle(el, null).getPropertyValue(prop) : '';
  30.         });
  31.  
  32.         return (computedStyle === val);
  33.     });
  34.  
  35.     /*
  36.     * debouncedresize: special jQuery event that happens once after a window resize
  37.     *
  38.     * latest version and complete README available on Github:
  39.     * https://github.com/louisremi/jquery-smartresize
  40.     *
  41.     * Copyright 2012 @louis_remi
  42.     * Licensed under the MIT license.
  43.     *
  44.     * This saved you an hour of work? 
  45.     * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON
  46.     */
  47.     var $event = $.event,
  48.     $special,
  49.     resizeTimeout;
  50.  
  51.     $special = $event.special.debouncedresize = {
  52.         setup: function() {
  53.             $( this ).on( "resize", $special.handler );
  54.         },
  55.         teardown: function() {
  56.             $( this ).off( "resize", $special.handler );
  57.         },
  58.         handler: function( event, execAsap ) {
  59.             // Save the context
  60.             var context = this,
  61.                 args = arguments,
  62.                 dispatch = function() {
  63.                     // set correct event type
  64.                     event.type = "debouncedresize";
  65.                     $event.dispatch.apply( context, args );
  66.                 };
  67.  
  68.             if ( resizeTimeout ) {
  69.                 clearTimeout( resizeTimeout );
  70.             }
  71.  
  72.             execAsap ?
  73.                 dispatch() :
  74.                 resizeTimeout = setTimeout( dispatch, $special.threshold );
  75.         },
  76.         threshold: 150
  77.     };
  78.  
  79.     $.BookBlock = function( options, element ) {
  80.         this.$el = $( element );
  81.         this._init( options );
  82.     };
  83.  
  84.     // the options
  85.     $.BookBlock.defaults = {
  86.         // page to start on
  87.         startPage : 1,
  88.         // vertical or horizontal flip
  89.         orientation : 'vertical',
  90.         // ltr (left to right) or rtl (right to left)
  91.         direction : 'ltr',
  92.         // speed for the flip transition in ms
  93.         speed : 1000,
  94.         // easing for the flip transition
  95.         easing : 'ease-in-out',
  96.         // if set to true, both the flipping page and the sides will have an overlay to simulate shadows
  97.         shadows : true,
  98.         // opacity value for the "shadow" on both sides (when the flipping page is over it)
  99.         // value : 0.1 - 1
  100.         shadowSides : 0.2,
  101.         // opacity value for the "shadow" on the flipping page (while it is flipping)
  102.         // value : 0.1 - 1
  103.         shadowFlip : 0.1,
  104.         // if we should show the first item after reaching the end
  105.         circular : false,
  106.         // if we want to specify a selector that triggers the next() function. example: ┬┤#bb-nav-next┬┤
  107.         nextEl : '',
  108.         // if we want to specify a selector that triggers the prev() function
  109.         prevEl : '',
  110.         // autoplay. If true it overwrites the circular option to true
  111.         autoplay : false,
  112.         // time (ms) between page switch, if autoplay is true
  113.         interval : 3000,
  114.         // callback after the flip transition
  115.         // old is the index of the previous item
  116.         // page is the current item┬┤s index
  117.         // isLimit is true if the current page is the last one (or the first one)
  118.         onEndFlip : function(old, page, isLimit) { return false; },
  119.         // callback before the flip transition
  120.         // page is the current item┬┤s index
  121.         onBeforeFlip : function(page) { return false; }
  122.     };
  123.  
  124.     $.BookBlock.prototype = {
  125.         _init : function(options) {
  126.             // options
  127.             this.options = $.extend( true, {}, $.BookBlock.defaults, options );
  128.             // orientation class
  129.             this.$el.addClass( 'bb-' + this.options.orientation );
  130.             // items
  131.             this.$items = this.$el.children( '.bb-item' ).hide();
  132.             // total items
  133.             this.itemsCount = this.$items.length;
  134.             // current item┬┤s index
  135.             if ( (this.options.startPage > 0) && (this.options.startPage <= this.itemsCount) ) {
  136.                 this.current = (this.options.startPage - 1);
  137.             } else {
  138.                 logError('startPage option is out of range');
  139.                 this.current = 0;
  140.             }
  141.             // previous item┬┤s index
  142.             this.previous = -1;
  143.             // show first item
  144.             this.$current = this.$items.eq( this.current ).show();
  145.             // get width of this.$el
  146.             // this will be necessary to create the flipping layout
  147.             this.elWidth = this.$el.width();
  148.             var transEndEventNames = {
  149.                 'WebkitTransition': 'webkitTransitionEnd',
  150.                 'MozTransition': 'transitionend',
  151.                 'OTransition': 'oTransitionEnd',
  152.                 'msTransition': 'MSTransitionEnd',
  153.                 'transition': 'transitionend'
  154.             };
  155.             this.transEndEventName = transEndEventNames[Modernizr.prefixed( 'transition' )] + '.bookblock';
  156.             // support css 3d transforms && css transitions && Modernizr.csstransformspreserve3d
  157.             this.support = Modernizr.csstransitions && Modernizr.csstransforms3d && Modernizr.csstransformspreserve3d;
  158.             // initialize/bind some events
  159.             this._initEvents();
  160.             // start slideshow
  161.             if ( this.options.autoplay ) {
  162.                 this.options.circular = true;
  163.                 this._startSlideshow();
  164.             }
  165.         },
  166.         _initEvents : function() {
  167.  
  168.             var self = this;
  169.  
  170.             if ( this.options.nextEl !== '' ) {
  171.                 $( this.options.nextEl ).on( 'click.bookblock touchstart.bookblock', function() { self._action( 'next' ); return false; } );
  172.             }
  173.  
  174.             if ( this.options.prevEl !== '' ) {
  175.                 $( this.options.prevEl ).on( 'click.bookblock touchstart.bookblock', function() { self._action( 'prev' ); return false; } );
  176.             }
  177.  
  178.             $window.on( 'debouncedresize', function() {        
  179.                 // update width value
  180.                 self.elWidth = self.$el.width();
  181.             } );
  182.  
  183.         },
  184.         _action : function( dir, page ) {
  185.             this._stopSlideshow();
  186.             this._navigate( dir, page );
  187.         },
  188.         _navigate : function( dir, page ) {
  189.  
  190.             if ( this.isAnimating ) {
  191.                 return false;
  192.             }
  193.  
  194.             // callback trigger
  195.             this.options.onBeforeFlip( this.current );
  196.  
  197.             this.isAnimating = true;
  198.             // update current value
  199.             this.$current = this.$items.eq( this.current );
  200.  
  201.             if ( page !== undefined ) {
  202.                 this.current = page;
  203.             }
  204.             else if ( dir === 'next' && this.options.direction === 'ltr' || dir === 'prev' && this.options.direction === 'rtl' ) {
  205.                 if ( !this.options.circular && this.current === this.itemsCount - 1 ) {
  206.                     this.end = true;
  207.                 }
  208.                 else {
  209.                     this.previous = this.current;
  210.                     this.current = this.current < this.itemsCount - 1 ? this.current + 1 : 0;
  211.                 }
  212.             }
  213.             else if ( dir === 'prev' && this.options.direction === 'ltr' || dir === 'next' && this.options.direction === 'rtl' ) {
  214.                 if ( !this.options.circular && this.current === 0 ) {
  215.                     this.end = true;
  216.                 }
  217.                 else {
  218.                     this.previous = this.current;
  219.                     this.current = this.current > 0 ? this.current - 1 : this.itemsCount - 1;
  220.                 }
  221.             }
  222.  
  223.             this.$nextItem = !this.options.circular && this.end ? this.$current : this.$items.eq( this.current );
  224.             
  225.             if ( !this.support ) {
  226.                 this._layoutNoSupport( dir );
  227.             } else {
  228.                 this._layout( dir );
  229.             }
  230.  
  231.         },
  232.         _layoutNoSupport : function(dir) {
  233.             this.$items.hide();
  234.             this.$nextItem.show();
  235.             this.end = false;
  236.             this.isAnimating = false;
  237.             var isLimit = dir === 'next' && this.current === this.itemsCount - 1 || dir === 'prev' && this.current === 0;
  238.             // callback trigger
  239.             this.options.onEndFlip( this.previous, this.current, isLimit );
  240.         },
  241.         // creates the necessary layout for the 3d structure
  242.         _layout : function(dir) {
  243.  
  244.             var self = this,
  245.                 // basic structure: 1 element for the left side.
  246.                 $s_left = this._addSide( 'left', dir ),
  247.                 // 1 element for the flipping/middle page
  248.                 $s_middle = this._addSide( 'middle', dir ),
  249.                 // 1 element for the right side
  250.                 $s_right = this._addSide( 'right', dir ),
  251.                 // overlays
  252.                 $o_left = $s_left.find( 'div.bb-overlay' ),
  253.                 $o_middle_f = $s_middle.find( 'div.bb-flipoverlay:first' ),
  254.                 $o_middle_b = $s_middle.find( 'div.bb-flipoverlay:last' ),
  255.                 $o_right = $s_right.find( 'div.bb-overlay' ),
  256.                 speed = this.end ? 400 : this.options.speed;
  257.  
  258.             this.$items.hide();
  259.             this.$el.prepend( $s_left, $s_middle, $s_right );
  260.             
  261.             $s_middle.css({
  262.                 transitionDuration: speed + 'ms',
  263.                 transitionTimingFunction : this.options.easing
  264.             }).on( this.transEndEventName, function( event ) {
  265.                 if ( $( event.target ).hasClass( 'bb-page' ) ) {
  266.                     self.$el.children( '.bb-page' ).remove();
  267.                     self.$nextItem.show();
  268.                     self.end = false;
  269.                     self.isAnimating = false;
  270.                     var isLimit = dir === 'next' && self.current === self.itemsCount - 1 || dir === 'prev' && self.current === 0;
  271.                     // callback trigger
  272.                     self.options.onEndFlip( self.previous, self.current, isLimit );
  273.                 }
  274.             });
  275.  
  276.             if ( dir === 'prev' ) {
  277.                 $s_middle.addClass( 'bb-flip-initial' );
  278.             }
  279.  
  280.             // overlays
  281.             if (this.options.shadows && !this.end) {
  282.  
  283.                 var o_left_style = (dir === 'next') ? {
  284.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear' + ' ' + this.options.speed / 2 + 'ms'
  285.                     } : {
  286.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear',
  287.                         opacity: this.options.shadowSides
  288.                     },
  289.                     o_middle_f_style = (dir === 'next') ? {
  290.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear'
  291.                     } : {
  292.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear' + ' ' + this.options.speed / 2 + 'ms',
  293.                         opacity: this.options.shadowFlip
  294.                     },
  295.                     o_middle_b_style = (dir === 'next') ? {
  296.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear' + ' ' + this.options.speed / 2 + 'ms',
  297.                         opacity: this.options.shadowFlip
  298.                     } : {
  299.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear'
  300.                     },
  301.                     o_right_style = (dir === 'next') ? {
  302.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear',
  303.                         opacity: this.options.shadowSides
  304.                     } : {
  305.                         transition: 'opacity ' + this.options.speed / 2 + 'ms ' + 'linear' + ' ' + this.options.speed / 2 + 'ms'
  306.                     };
  307.  
  308.                 $o_middle_f.css(o_middle_f_style);
  309.                 $o_middle_b.css(o_middle_b_style);
  310.                 $o_left.css(o_left_style);
  311.                 $o_right.css(o_right_style);
  312.  
  313.             }
  314.  
  315.             setTimeout( function() {
  316.                 // first && last pages lift slightly up when we can't go further
  317.                 $s_middle.addClass( self.end ? 'bb-flip-' + dir + '-end' : 'bb-flip-' + dir );
  318.  
  319.                 // overlays
  320.                 if ( self.options.shadows && !self.end ) {
  321.  
  322.                     $o_middle_f.css({
  323.                         opacity: dir === 'next' ? self.options.shadowFlip : 0
  324.                     });
  325.  
  326.                     $o_middle_b.css({
  327.                         opacity: dir === 'next' ? 0 : self.options.shadowFlip
  328.                     });
  329.  
  330.                     $o_left.css({
  331.                         opacity: dir === 'next' ? self.options.shadowSides : 0
  332.                     });
  333.  
  334.                     $o_right.css({
  335.                         opacity: dir === 'next' ? 0 : self.options.shadowSides
  336.                     });
  337.  
  338.                 }
  339.             }, 25 );
  340.         },
  341.         // adds the necessary sides (bb-page) to the layout 
  342.         _addSide : function( side, dir ) {
  343.             var $side;
  344.  
  345.             switch (side) {
  346.                 case 'left':
  347.                         /*
  348.                         <div class="bb-page" style="z-index:102;">
  349.                             <div class="bb-back">
  350.                                 <div class="bb-outer">
  351.                                     <div class="bb-content">
  352.                                         <div class="bb-inner">
  353.                                             dir==='next' ? [content of current page] : [content of next page]
  354.                                         </div>
  355.                                     </div>
  356.                                     <div class="bb-overlay"></div>
  357.                                 </div>
  358.                             </div>
  359.                         </div>
  360.                         */
  361.                     $side = $('<div class="bb-page"><div class="bb-back"><div class="bb-outer"><div class="bb-content"><div class="bb-inner">' + ( dir === 'next' ? this.$current.html() : this.$nextItem.html() ) + '</div></div><div class="bb-overlay"></div></div></div></div>').css( 'z-index', 102 );
  362.                     break;
  363.                 case 'middle':
  364.                         /*
  365.                         <div class="bb-page" style="z-index:103;">
  366.                             <div class="bb-front">
  367.                                 <div class="bb-outer">
  368.                                     <div class="bb-content">
  369.                                         <div class="bb-inner">
  370.                                             dir==='next' ? [content of current page] : [content of next page]
  371.                                         </div>
  372.                                     </div>
  373.                                     <div class="bb-flipoverlay"></div>
  374.                                 </div>
  375.                             </div>
  376.                             <div class="bb-back">
  377.                                 <div class="bb-outer">
  378.                                     <div class="bb-content">
  379.                                         <div class="bb-inner">
  380.                                             dir==='next' ? [content of next page] : [content of current page]
  381.                                         </div>
  382.                                     </div>
  383.                                     <div class="bb-flipoverlay"></div>
  384.                                 </div>
  385.                             </div>
  386.                         </div>
  387.                         */
  388.                     $side = $('<div class="bb-page"><div class="bb-front"><div class="bb-outer"><div class="bb-content"><div class="bb-inner">' + (dir === 'next' ? this.$current.html() : this.$nextItem.html()) + '</div></div><div class="bb-flipoverlay"></div></div></div><div class="bb-back"><div class="bb-outer"><div class="bb-content" style="width:' + this.elWidth + 'px"><div class="bb-inner">' + ( dir === 'next' ? this.$nextItem.html() : this.$current.html() ) + '</div></div><div class="bb-flipoverlay"></div></div></div></div>').css( 'z-index', 103 );
  389.                     break;
  390.                 case 'right':
  391.                         /*
  392.                         <div class="bb-page" style="z-index:101;">
  393.                             <div class="bb-front">
  394.                                 <div class="bb-outer">
  395.                                     <div class="bb-content">
  396.                                         <div class="bb-inner">
  397.                                             dir==='next' ? [content of next page] : [content of current page]
  398.                                         </div>
  399.                                     </div>
  400.                                     <div class="bb-overlay"></div>
  401.                                 </div>
  402.                             </div>
  403.                         </div>
  404.                         */
  405.                     $side = $('<div class="bb-page"><div class="bb-front"><div class="bb-outer"><div class="bb-content"><div class="bb-inner">' + ( dir === 'next' ? this.$nextItem.html() : this.$current.html() ) + '</div></div><div class="bb-overlay"></div></div></div></div>').css( 'z-index', 101 );
  406.                     break;
  407.             }
  408.  
  409.             return $side;
  410.         },
  411.         _startSlideshow : function() {
  412.             var self = this;
  413.             this.slideshow = setTimeout( function() {
  414.                 self._navigate( 'next' );
  415.                 if ( self.options.autoplay ) {
  416.                     self._startSlideshow();
  417.                 }
  418.             }, this.options.interval );
  419.         },
  420.         _stopSlideshow : function() {
  421.             if ( this.options.autoplay ) {
  422.                 clearTimeout( this.slideshow );
  423.                 this.options.autoplay = false;
  424.             }
  425.         },
  426.         // public method: flips next
  427.         next : function() {
  428.             this._action( this.options.direction === 'ltr' ? 'next' : 'prev' );
  429.         },
  430.         // public method: flips back
  431.         prev : function() {
  432.             this._action( this.options.direction === 'ltr' ? 'prev' : 'next' );
  433.         },
  434.         // public method: goes to a specific page
  435.         jump : function( page ) {
  436.  
  437.             page -= 1;
  438.  
  439.             if ( page === this.current || page >= this.itemsCount || page < 0 ) {
  440.                 return false;
  441.             }
  442.  
  443.             var dir;
  444.             if( this.options.direction === 'ltr' ) {
  445.                 dir = page > this.current ? 'next' : 'prev';
  446.             }
  447.             else {
  448.                 dir = page > this.current ? 'prev' : 'next';
  449.             }
  450.             this._action( dir, page );
  451.  
  452.         },
  453.         // public method: goes to the last page
  454.         last : function() {
  455.             this.jump( this.itemsCount );
  456.         },
  457.         // public method: goes to the first page
  458.         first : function() {
  459.             this.jump( 1 );
  460.         },
  461.         // public method: check if isAnimating is true
  462.         isActive: function() {
  463.             return this.isAnimating;
  464.         },
  465.         // public method: dynamically adds new elements
  466.         // call this method after inserting new "bb-item" elements inside the BookBlock
  467.         update : function () {
  468.             var $currentItem = this.$items.eq( this.current );
  469.             this.$items = this.$el.children( '.bb-item' );
  470.             this.itemsCount = this.$items.length;
  471.             this.current = $currentItem.index();
  472.         },
  473.         destroy : function() {
  474.             if ( this.options.autoplay ) {
  475.                 this._stopSlideshow();
  476.             }
  477.             this.$el.removeClass( 'bb-' + this.options.orientation );
  478.             this.$items.show();
  479.  
  480.             if ( this.options.nextEl !== '' ) {
  481.                 $( this.options.nextEl ).off( '.bookblock' );
  482.             }
  483.  
  484.             if ( this.options.prevEl !== '' ) {
  485.                 $( this.options.prevEl ).off( '.bookblock' );
  486.             }
  487.  
  488.             $window.off( 'debouncedresize' );
  489.         }
  490.     }
  491.  
  492.      var logError = function( message ) {
  493.         if ( window.console ) {
  494.             window.console.error( message );
  495.         }
  496.     };
  497.  
  498.     $.fn.bookblock = function( options ) {
  499.         if ( typeof options === 'string' ) {
  500.             var args = Array.prototype.slice.call( arguments, 1 );
  501.             this.each(function() {
  502.                 var instance = $.data( this, 'bookblock' );
  503.                 if ( !instance ) {
  504.                     logError( "cannot call methods on bookblock prior to initialization; " +
  505.                     "attempted to call method '" + options + "'" );
  506.                     return;
  507.                 }
  508.                 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
  509.                     logError( "no such method '" + options + "' for bookblock instance" );
  510.                     return;
  511.                 }
  512.                 instance[ options ].apply( instance, args );
  513.             });
  514.         } 
  515.         else {
  516.             this.each(function() {    
  517.                 var instance = $.data( this, 'bookblock' );
  518.                 if ( instance ) {
  519.                     instance._init();
  520.                 }
  521.                 else {
  522.                     instance = $.data( this, 'bookblock', new $.BookBlock( options, this ) );
  523.                 }
  524.             });
  525.         }
  526.         return this;
  527.     };
  528.  
  529. } )( jQuery, window );
  530.