/** * jQuery.flickSimple v1.2.2 * * Copyright (c) 2011 Makog. http://d.hatena.ne.jp/makog/ * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * */ (function($){ $.flickSimple = function( obj, param ) { this.setup( $(obj), param ); }; $.extend( $.flickSimple.prototype, { elm: null, target: null, disabled: false, snap: 'element', ratio: 5, duration: 600, lock: false, onChange: null, onResize: null, onAnimationEnd: null, onClick: null, vertical: false, horizontal: true, paginate: 'x', elmWidth: 0, elmHeight: 0, page: 1, pageWidth: 0, pageHeight: 0, pageLength: 0, android: false, touchable: ( typeof ontouchstart !== 'undefined' ), vender: (function() { var props = [ [ '-webkit-transition', '-webkit-transition', '-webkit-transform', 'webkitTransitionEnd' ], [ 'MozTransition', '-moz-transition', '-moz-transform', 'transitionend' ], [ 'OTransition', '-o-transition', '-o-transform', 'oTransitionEnd' ], [ '-ms-transition', '-ms-transition', '-ms-transform', 'msTransitionEnd' ], [ 'transition', 'transition', 'transform', 'transitionEnd' ] ]; var div = document.createElement('div'); var vender = {}; for( var i=0,len=props.length; i this.pageLength ) { pagenum = this.pageLength; } pagenum--; var pageX, pageY, rownum; if ( this.paginate === 'y' ) { rownum = Math.ceil( this.elmHeight / this.pageHeight ) +1; pageX = Math.floor( pagenum / rownum ); pageY = pagenum % rownum; } else { rownum = Math.ceil( this.elmWidth / this.pageWidth ) +1; pageY = Math.floor( pagenum / rownum ); pageX = pagenum % rownum; } var posX = pageX * this.pageWidth; var posY = pageY * this.pageHeight; return this.move( -posX, -posY ); }, // 指定されたX座標に移動 move: function( posX, posY ) { var o = this; if ( ! o.horizontal || posX >= 0 ) { posX = 0; } else if ( posX < -o.elmWidth ) { posX = -o.elmWidth; } if ( ! o.vertical || posY >= 0 ) { posY = 0; } else if ( posY < -o.elmHeight ) { posY = -o.elmHeight; } if ( ! o.useCSSAnim ) { o.target.animate( { left: posX + 'px', top: posY + 'px' }, function (e) { if ( o.onAnimationEnd ) { o.onAnimationEnd(e); } } ); } else { var css = {}; css[o.vender.transition] = o.vender.transform + ' 0.3s ease-in'; css[o.vender.transform] = o.use3d ? 'translate3d(' + posX + 'px,' + posY + 'px,0)' : 'translate(' + posX + 'px,' + posY + 'px)'; o.target.css(css); } o.nextX = posX; o.nextY = posY; return o.update( posX, posY ); }, // 表示が変更されたら、各エレメントの大きさを計算し直す updateSize: function() { var o = this; var ori = typeof( window.orientation ) !== 'undefined' ? ( window.orientation === 0 ? 'portrait' : 'landscape' ) : ( window.innerWidth < window.innerHeight ? 'portrait' : 'landscape' ); // var lis = o.target.find('li'); var lis = o.target.children(); o.elm.removeClass('landscape portrait').addClass( ori ); // うまく反映されない場合があるので、エレメント自体にclassを振る o.target.removeClass('landscape portrait').addClass( ori ); lis.removeClass('landscape portrait').addClass( ori ); var targw = o.target.width(); var targh = o.target.height(); var elmw = o.elm.width(); var elmh = o.elm.height(); o.elmWidth = targw - elmw; o.elmHeight = targh - elmh; o.pageWidth = 0; o.pageHeight = 0; o.pageLength = 0; if ( o.snap ) { if ( o.snap === 'element' ) { o.pageWidth = elmw; o.pageHeight = elmh; } else if ( o.snap === 'first' ) { o.pageWidth = $(lis.get(0)).width(); o.pageHeight = $(lis.get(0)).height(); } else if ( o.snap === 'smallest' ) { var smaller = 0; lis.each( function() { var w = $(this).width(); if ( smaller > w || smaller == 0 ) { smaller = w; } } ); o.pageWidth = smaller; smaller = 0; lis.each( function() { var h = $(this).height(); if ( smaller > h || smaller == 0 ) { smaller = h; } } ); o.pageHeight = smaller; } else if ( typeof o.snap === 'object' ) { o.pageWidth = o.snap[0]; o.pageHeight = o.snap[1]; } else if ( ! isNaN(o.snap) ) { o.pageWidth = o.snap; o.pageHeight = o.snap; } o.pageLength = Math.ceil( targw / o.pageWidth ); if ( targh > o.pageHeight ) { o.pageLength *= Math.ceil( targh / o.pageHeight ); } } if ( o.onResize ) { o.onResize(); } if ( o.snap ) { o.goTo( o.page ); } return o; }, touchstart: function(e) { var o = this; var te = o.touchable ? e.originalEvent.touches[0] : e; if ( o.disabled ) { return; } o.startX = o.preX = te.clientX; o.startY = o.preY = te.clientY; o.touchhold = false; var anc = e.target.tagName === 'A' ? $(e.target) : $(e.target).closest('a'); if ( anc.length > 0 ) { o.anc = anc; } // 長押し対応 setTimeout( function() { if ( o.anc ) { // o.startX = null; o.touchhold = true; var anc = o.anc; var link = $.data(anc.get(0), 'flickSimple.link' ); if ( link ) { anc.attr('href', link); setTimeout( function() { anc && anc.attr('href', 'javascript:;'); }, 200 ); } } }, 600 ); }, touchmove: function(e) { var o = this; if ( o.disabled ) { return; } if ( o.android || o.lock ) { e.preventDefault(); } if ( o.startX === null || o.startY === null ) { o.anc = null; return; } var te = o.touchable ? e.originalEvent.touches[0] : e; var nowX = te.clientX; var nowY = te.clientY; if ( Math.abs( o.startX - nowX ) > 16 || Math.abs( o.startY - te.clientY ) > 16 ) { o.anc = null; } o.nextX = o.horizontal ? (o.currentX || 0) + ( nowX - o.startX ) : 0; o.nextY = o.vertical ? (o.currentY || 0) + ( nowY - o.startY ) : 0; if ( ! o.useCSSAnim ) { o.target.css( { left: o.nextX + 'px', top: o.nextY + 'px' } ); } else { var css = {}; css[o.vender.transition] = 'none'; css[o.vender.transform] = o.use3d ? 'translate3d(' + o.nextX + 'px,' + o.nextY + 'px,0)' : 'translate(' + o.nextX + 'px,' + o.nextY + 'px)'; o.target.css( css ); } o.flickX = o.preX - nowX; o.flickY = o.preY - nowY; o.preX = nowX; o.preY = nowY; }, touchend: function(e) { var o = this; if ( o.disabled || o.startX === null || o.startY === null ) { return; } o.startX = null; o.startY = null; if ( o.anc && ! o.touchhold ) { if ( o.onClick ) { o.onClick( o.anc ); } var ancr = o.anc.get(0); var link = $.data(ancr, 'flickSimple.link' ); var targ = $.data(ancr, 'flickSimple.target' ); if ( link ) { if ( targ && targ !== '_self' ) { if ( targ === '_blank' ) { targ = ''; } window.open( link, targ ); } else { location.href = link; } } e.preventDefault(); } o.touchhold = false; var nposX = o.nextX + (o.flickX * -o.ratio); var nposY = o.nextY + (o.flickY * -o.ratio); if ( o.pageWidth ) { var thrX = nposX % o.pageWidth; if ( thrX < -o.pageWidth / 2 ) { nposX -= thrX + o.pageWidth; } else { nposX -= thrX; } var thrY = nposY % o.pageHeight; if ( thrY < -o.pageHeight / 2 ) { nposY -= thrY + o.pageHeight; } else { nposY -= thrY; } } if ( ! o.horizontal || nposX >= 0 ) { nposX = 0; } else if ( nposX < -o.elmWidth ) { nposX = -o.elmWidth; } if ( ! o.vertical || nposY >= 0 ) { nposY = 0; } else if ( nposY < -o.elmHeight ) { nposY = -o.elmHeight; } if ( ! o.useCSSAnim ) { o.target.animate( { left: nposX + 'px', top: nposY + 'px' }, o.duration, function (x, t, b, c, d) { if ( o.onAnimationEnd ) { o.onAnimationEnd(e); } return -c *(t/=d)*(t-2) + b; } ); } else { var css = {}; css[o.vender.transition] = o.vender.transform + ' ' + (o.duration / 1000) + "s ease-out"; css[o.vender.transform] = o.use3d ? 'translate3d(' + nposX + 'px,' + nposY + 'px,0)' : 'translate(' + nposX + 'px,' + nposY + 'px)'; o.target.css( css ); } o.update( nposX, nposY ); }, update: function( posX, posY ) { var o = this; if ( o.pageWidth || o.pageHeight ) { var rownum; if ( o.paginate === 'y' ) { rownum = Math.ceil( this.elmHeight / this.pageHeight ) +1; o.page = Math.ceil( -posY / o.pageHeight ) + ( Math.ceil( -posX / o.pageWidth ) * rownum) +1; } else { rownum = Math.ceil( this.elmWidth / this.pageWidth ) +1; o.page = Math.ceil( -posX / o.pageWidth ) + (Math.ceil( -posY / o.pageHeight ) * rownum) +1; } } if ( o.currentX !== posX || o.currentY !== posY ) { o.currentX = posX; o.currentY = posY; if ( o.onChange ) { o.onChange(); } } return o; }, no_mousedown: function(e) { e.preventDefault(); }, // 初期化(内容に変更があった場合には、呼び出すこと) init: function() { var o = this; o.target.find('a').each( function() { var obj = $(this); var link = obj.attr('href'); var targ = obj.attr('target'); if ( link && link !== 'javascript:;' ) { $.data(this, 'flickSimple.link', link ); } $.data(this, 'flickSimple.target', targ || '' ); obj.attr('href', 'javascript:;').removeAttr('target'); if ( ! o.touchable ) { obj.unbind( 'mousedown', o.no_mousedown ) .bind( 'mousedown', o.no_mousedown ); } } ); // 画像のドラッグをさせない if ( ! o.touchable ) { o.target.find('img') .unbind( 'mousedown', o.no_mousedown ) .bind( 'mousedown', o.no_mousedown ); } return o; } } ); $.fn.flickSimple = function( param ) { var res = this; if ( typeof param === "string" ) { // 引数が文字列の場合 var args = Array.prototype.slice.call(arguments, 1); this.each( function() { var instance = $.data(this, 'flickSimple'); var val; if ( instance ) { if ( $.isFunction(instance[param]) ) { val = instance[param].apply(instance, args); } else { if ( args.length > 0 ) { instance[param] = args[1]; } val = instance[param]; } } if ( val !== instance ) { res = val } }); } else { this.each( function() { var instance = $.data(this, 'flickSimple'); if (! instance) { $.data(this, 'flickSimple', new $.flickSimple( this, param || {} ) ); } else { res = instance; } } ); } return res; }; })(jQuery);