jRoulette
a touch enabled image browser
jRoulette is an image slideshow carousel which means that the slides loop from the end to the beginning and vice versa. Developed as a jQuery plugin, jRoulette supports swipe gestures, automatic start, pagination, and left/right bumpers. Although the final version retains little semblance to the original, Andrew Marcus & Love Media jBond Slider served as the inspiration and the code starting point. Many thanks!
<!doctype html> <html> <head> <meta charset="utf-8" /> <title>>arg¡eBarg!e: jRoulette</title> <meta name="description" content="…a continuous image carousel." /> <meta name="author" content="Henry Rogers" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <!-- Adding "maximum-scale=1" fixes the Mobile Safari auto-zoom bug: http://filamentgroup.com/examples/iosScaleBug/ --> <link type="text/css" rel="stylesheet" href="jroulette.css" /> </head> <body lang="en"> <div id="header-container" class="wrapper lab"> <header> <h1>>arg¡eBarg!e:</h1> <span>…such as an argument, often a worthless, but energetic, conversation or comment.</span> </header> </div> <div id="main" class="wrapper lab" role="main"> <article> <header> <div style="float:right"> <a href="https://github.com/hhrogersii/argleBargle/tree/master/jroulette/"><img id="octodex" src="/img/octodex.png" width="24" height="24" alt="Git'er Done" /></a> ← <a href="http://hhrogersii.com/lab/jroulette/">jRoulette</a> ← <a href="http://hhrogersii.com/lab/">arg¡eBarg!e</a> ← <a href="http://hhrogersii.com/">hhROGERSii</a> </div> <h2>jRoulette</h2> <p>…a continuous image carousel.</p> </header> <section> <div class="section" style="position:relative"> <h3>Paul Klee</h3> <div class="jroulette"> <div class="roul-touchmargin"> <div class="roul-bump-left"></div> <div class="roul-wrap"> <div class="roul-boxy"> <div class="roul-slds" id="slide-0" style="left:0px"> <img src="klee_1914.jpg" alt="1914" width="300" height="360" /> </div> <div class="roul-slds" id="slide-1" style="left:640px"> <img src="klee_ancient-sound.jpg" alt="Ancient Sound" width="348" height="360" /> </div> <div class="roul-slds" id="slide-2" style="left:1280px"> <img src="klee_captive.jpg" alt="Captive" width="321" height="360" /> </div> <div class="roul-slds" id="slide-3" style="left:1920px"> <img src="klee_dream-city.jpg" alt="Dream City" width="232" height="360" /> </div> <div class="roul-slds" id="slide-4" style="left:2560px"> <img src="klee_embrace.jpg" alt="Embrace" width="448" height="360" /> </div> <div class="roul-slds" id="slide-5" style="left:3200px"> <img src="klee_highway-byways.jpg" alt="Highway Byways" width="285" height="360" /> </div> <div class="roul-slds" id="slide-6" style="left:3840px"> <img src="klee_park-idols.jpg" alt="Park Idols" width="225" height="360" /> </div> <div class="roul-slds" id="slide-7" style="left:4480px"> <img src="klee_parnassum.jpg" alt="Parnassum" width="458" height="360" /> </div> <div class="roul-slds" id="slide-8" style="left:4480px"> <img src="klee_tunisian-gardens.jpg" alt="Tunisian Gardens" width="273" height="360" /> </div> <div class="roul-slds" id="slide-9" style="left:4480px"> <img src="paul_klee_artist.jpg" alt="Paul Klee the artist" width="485" height="360" /> </div> </div> </div> <div class="roul-bump-right"></div> </div> <div class="roul-page"> <ul> <li id="page-0"><a href="##page-0"></a></li> <li id="page-1"><a href="##page-1"></a></li> <li id="page-2"><a href="##page-2"></a></li> <li id="page-3"><a href="##page-3"></a></li> <li id="page-4"><a href="##page-4"></a></li> <li id="page-5"><a href="##page-5"></a></li> <li id="page-6"><a href="##page-6"></a></li> <li id="page-7"><a href="##page-7"></a></li> <li id="page-8"><a href="##page-8"></a></li> <li id="page-9"><a href="##page-9"></a></li> </ul> </div> </div> </div> </section> <footer> <p> <a href="https://github.com/hhrogersii/argleBargle/tree/master/jroulette/"><img id="octodex" src="/img/octodex.png" width="24" height="24" alt="Git'er Done" /></a> ← <a href="http://hhrogersii.com/lab/jroulette/">jRoulette</a> ← <a href="http://hhrogersii.com/lab/">arg¡eBarg!e</a> ← <a href="http://hhrogersii.com/">hhROGERSii</a> </p> </footer> </article> </div> <div id="footer-container" class="wrapper lab"> <footer> <p>All code authored by hhrogersii is available for use with or without attribution under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. <br />See disclaimers provided by the authors of code included in this site for the terms and conditions of the use of their work.</p> </footer> </div> <!--Thank you jQuery --> <script src="http://code.jquery.com/jquery-latest.js"></script> <script>!window.jQuery && document.write(unescape('%3Cscript src="/js/libs/jquery-1.5.1.min.js"%3E%3C/script%3E'))</script> <script type="text/javascript" src="jroulette.js"></script> <script> $(document).ready( function(){ $('.roul-touchmargin').jRoulette( { desktopMode:'touchMargin', mobileMode:'touchMargin' } ); } ); </script> </body> </html>
/*jslint browser: true, undef: false, sloppy: true, vars: true, white: true, forin: false, nomen: false, maxerr: 100, indent: 4 */ /*globals document,$,jQuery*/ /* * jRoulette v0.1 * Designed and written by hhrogersii * Licensed under MIT * Inspired by jBond Slider 0.9 * Andrew Marcus & Love Media, 2010 * Licensed under MIT */ (function ($) { 'use strict'; $.fn.extend( { jRoulette: function ( opt ) { jQuery.extend( jQuery.easing , { roul_ease: function ( x, t, b, c, d ) { x = x; return ( t === d ) ? b+c : c*(-Math.pow(2,-10*t/d)+1)+b; } } ); var dflts = { scroll: 3 , bounce: 4 , veloce: 5 , neutra: 6 // Rest area width in px , mspeed: 7 // Max speed , wrapSelector: '.roul-wrap' , boxySelector: '.roul-boxy' , sldsSelector: '.roul-slds' , bumpSelector: '.roul-bump' , pageSelector: '.roul-page' , easingMargin: 'swing' //'roul_ease' , slideClickCallback: function ( i, d ) { i = d; } } , option = {}; if ( !opt ) { opt = dflts; } else { for ( option in dflts ) { if ( dflts.hasOwnProperty(option) && opt[option] === undefined ) { opt[option] = dflts[option]; } } } //private function getLeft ( f ) { return parseInt( f.css('left'), 10 ); } function setLeft ( f, d ) { f.css( 'left', ( getLeft(f) + d ) ); } function wrapIndex ( v, l ) { return ( v + l ) % l; } function manual ( i ) { clearInterval( i ); } //public return this.each( function () { var roul = $(this) , wrap = roul.children( opt.wrapSelector ) , boxy = wrap.children( opt.boxySelector ) , slds = boxy.children( opt.sldsSelector ) , scnt = slds.length , frst = slds.first() , bump = roul.children( opt.bumpSelector+'-left,' +opt.bumpSelector+'-right' ) , page = $( opt.pageSelector ).find('li') , sdim = frst.width() , adim = scnt * sdim , touch = 0, delta = 0, veloc = 0, crrnt = 0, dirct = 0, autos = 0 ; function animate ( target, fn ) { var callback = ( !fn ) ? jQuery.noop : fn , time = parseFloat( (opt.scroll).toString() + 's' ) * 1000; page.removeClass('hover'); frst.animate( { 'left': target } , { duration: time , easing: opt.easingMargin , complete: callback , step: function ( now ) { slds.css( 'left' , function ( index ) { return ( (index * sdim) + now ) % adim; } ); } } ); page.eq( ( scnt - crrnt ) % scnt ).addClass('hover'); } function change ( e, c, d ) { manual( autos ); slds.stop( true ); e.preventDefault(); e.stopPropagation(); crrnt = c; dirct = d; } function select ( e, p ) { if ( scnt-p === crrnt ) { return false; } var cur = crrnt; var tar = scnt - p; var dis = cur - tar; var abs = Math.abs( dis ); var opp = scnt - abs; var dir = abs / dis; //var shift = Math.min( abs , (scnt-abs) ) * abs / dis; var shf = ( ( tar < cur ) ? ( ( abs < opp ) ? 1 : -1 ) : ( ( abs < opp ) ? -1 : 1 ) ); if ( shf !== dir ) { setLeft( frst, ( adim * -dir ) ); } change( e , tar , dir ); animate( tar * sdim ); } function browse ( e, d ) { if ( ( d > 0 && crrnt === scnt-1 ) || ( d < 0 && crrnt === 0 ) ) { setLeft( frst, ( adim * -d ) ); } change( e , wrapIndex( ( crrnt + d ), scnt ) , d ); animate( crrnt * sdim ); } function automatic() { autos = window.setInterval( function () { if ( crrnt === 0 ) { setLeft( frst, adim ); } slds.stop( true ); crrnt = wrapIndex( ( crrnt + -1 ), scnt ); dirct = -1; animate( crrnt * sdim ); } , 4000 ); } function back () { crrnt = wrapIndex( ( -Math.round( getLeft( frst ) / sdim ) ), scnt ); var shift = wrapIndex( ( -crrnt ), scnt ) * sdim; if ( shift === 0 && getLeft( frst ) > 2400 ) { setLeft( frst, ( adim * dirct ) ); } animate( shift ); } function end () { touch = 0; if ( Math.abs(veloc) > opt.veloce ) { animate( getLeft( frst ) + Math.floor( Math.sqrt( Math.abs(veloc) * opt.bounce ) ) * veloc, back ); } else { back(); } slds.unbind( 'mousemove move' ); $(document).unbind( 'mouseup end' ); return false; } function move ( x ) { veloc = x - touch - delta; delta = x - touch; dirct = Math.abs(veloc)/veloc; slds.css( 'left' , function ( index ) { return wrapIndex( (index * sdim) + delta, adim ); } ); return false; } function begin ( e ) { if ( e.button === 2 ) { return false; } var me = ( e.originalEvent && e.originalEvent.touches ) ? e.originalEvent.touches[0] : e; slds.stop(); e.preventDefault(); e.stopPropagation(); manual( autos ); delta = 0; veloc = 0; touch = me.pageX - getLeft( frst ); slds.on( 'mousemove move' , function (me) { move(me.pageX); } ); $(document).on( 'mouseup end' , function () { end(); } ); return false; } roul.find('a').click( function () { if ( delta !== 0 ) { return false; } } ); /* Setting zero position */ wrap.css( 'left' , ( ( ( Math.ceil( (scnt+1) / 2 ) - 1 ) * -sdim ) ).toString() + 'px' ); boxy.children( opt.sldsSelector ).click( function () { opt.slideClickCallback( slds.index(this), delta ); } ); slds.on( 'mousedown begin' , function (e) { begin(e); } ); bump.on( { click: function(e) { if ( touch === 0 ) { browse( e, ( $(this).attr('class').indexOf('right')>0 ? -1 : 1 ) ); } } , mouseenter: function() { if ( touch === 0 ) { $(this).addClass('hover'); } } , mouseleave: function() { $(this).removeClass('hover'); } } ); page.on( { click: function (e) { select( e, $(this).index() ); } , mouseenter: function() { $(this).addClass('hover'); } , mouseleave: function() { $(this).removeClass('hover'); } } ); automatic(); } );//end public }//end roul }//end map );//end extend }( jQuery ) );
.jroulette { padding-bottom:30px; width:660px; } .roul-touchmargin { height: 360px; position: relative; overflow: hidden; width: 640px; border: 10px solid #fff7d1; } .roul-wrap { -webkit-transform: translate3d(0px, 0px, 0px); -webkit-transition-property: -webkit-transform; -webkit-transition-duration: 0s; -webkit-transition-timing-function: cubic-bezier(0,1,1,1); position: absolute; left: 0; top: 0; } .roul-wrap a { -webkit-transition: none; -moz-transition: none; -o-transition: none; transition: none; border: none; } .roul-boxy { width: 4480px; } .roul-slds { margin: 0; width: 640px; position: absolute; text-align: center; background-color: #e4e2d3; } .roul-slds img { /* width: 640px; */ height: 360px; border: none; } .roul-slds a { cursor:move; } .roul-bump-left, .roul-bump-right { background-color: white; width: 40px; height: 360px; opacity: .0; -moz-opacity: .0; cursor: pointer; } .roul-bump-left.hover, .roul-bump-right.hover { opacity: .7; -moz-opacity: .7; } .roul-bump-left.hover { background: no-repeat url('/img/arrow_next_left.png') center center rgba(255,255,255,0.6); } .roul-bump-right.hover { background: no-repeat url('/img/arrow_next_right.png') center center rgba(255,255,255,0.6); } .roul-bump-left { float: left; position: absolute; z-index: 100; } .roul-bump-right { float: right; } .roul-page { text-align: center; float: left; width: 660px; } .roul-page ul { list-style-position: inside; list-style-type:decimal; display: inline-block; } .roul-page li { color: #aa8b64; width: 26px; float: left; font-size:16px; margin: 2px; padding: 4px 0 4px 8px } .roul-page li.hover { text-shadow: 0px 0px 3px; /* -moz-box-shadow:inset 0 0 6px 6px #ECE5CF; -webkit-box-shadow:inset 0 0 6px 6px #ECE5CF; box-shadow:inset 0 0 6px 6px #ECE5CF; background-color: #b89e8a; */ color: #333; } .roul-page li a { position:absolute; left:-1000px; }