Skip to content
Browse files

Teaser.

  • Loading branch information...
0 parents commit e0277168679fb19984874d3080c217ce4d1139d3 @nathanhammond committed Mar 8, 2011
Showing with 345 additions and 0 deletions.
  1. +6 −0 README.md
  2. +58 −0 index.html
  3. +27 −0 jquery.gallery.css
  4. +254 −0 jquery.gallery.js
6 README.md
@@ -0,0 +1,6 @@
+#Building jQuery Plugins for Fun and/or Profit.
+I'll be giving this presentation on 3/17/2010 at CharlotteJS! Come to the meetup!
+http://www.charlottejs.org/events/15689336/
+
+##Sneak Preview
+If you want a sneak preview of my slide mechanism (which you'll be learning how to build!) check out this repo and take a look in Safari or Chrome Dev (up-to-date).
58 index.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Building jQuery Plugins for Fun and/or Profit.</title>
+<style type="text/css">
+ * { margin: 0; padding: 0; }
+ html, body { width: 100%; height: 100%; background: #000; overflow: hidden; }
+ #container { width: 100%; height: 100%; background: #000; }
+ .item { position: absolute; display: block; width: 100%; height: 100%; background: #FFF;}
+</style>
+<link rel="stylesheet" href="jquery.gallery.css" type="text/css" />
+</head>
+<body>
+ <div id="container" class="gallerycontainer">
+ <div class="item">
+ <table cellspacing="0" style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center;">
+ <h1>Building jQuery Plugins for Fun and/or Profit.</h1>
+ <h2>Nathan Hammond</h2>
+ </td></tr></table>
+ </div>
+ <div class="item">
+ <h1>Slide 1</h1>
+ </div>
+ <div class="item">
+ <h1>Slide 2</h1>
+ </div>
+ <div class="item">
+ <h1>Slide 3</h1>
+ </div>
+ <div class="item">
+ <table cellspacing="0" style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center;">
+ <h1>Questions?</h1>
+ </td></tr></table>
+ </div>
+ </div>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js"></script>
+ <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
+ <script type="text/javascript" src="jquery.gallery.js"></script>
+ <script type="text/javascript">
+ var timeout;
+ $('#container').gallery();
+ $('body').live("keydown", function(e) {
+
+ switch (e.which) {
+ case 38: clearTimeout(timeout); $('.gallery').css({zoom:.5}); timeout = setTimeout(function() {$('.gallery').css({zoom:1}); }, 750); break;
+ case 40: clearTimeout(timeout); $('.gallery').css({zoom:.5}); timeout = setTimeout(function() {$('.gallery').css({zoom:1}); }, 750); break;
+ case 37: clearTimeout(timeout); $('.gallery').css({zoom:.5}); $('#container').gallery('prev'); timeout = setTimeout(function() {$('.gallery').css({zoom:1}); }, 750); break;
+ case 39: clearTimeout(timeout); $('.gallery').css({zoom:.5}); $('#container').gallery('next'); timeout = setTimeout(function() {$('.gallery').css({zoom:1}); }, 750); break;
+ default: break;
+ }
+
+ });
+ </script>
+</body>
+</html>
27 jquery.gallery.css
@@ -0,0 +1,27 @@
+.gallerycontainer { background: #000; overflow: hidden; }
+
+.gallery { position: relative; overflow: visible; margin: 0 auto; list-style-position: outside; list-style: none; }
+.gallery li { position: absolute; list-style: none; bottom: 0; }
+.gallery li .item { display: block; width: 100%; }
+
+.skirt { z-index: 10000; position: relative; background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0)), color-stop(1, rgba(0,0,0,1))); }
+
+.gallery .item {
+ -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255,255,255,.4)));
+}
+.gallery li {
+ -webkit-transform: perspective(200) translateZ(-70px) rotateY(31deg);
+ -webkit-transition: -webkit-transform .5s, left .5s;
+}
+.gallery li.focus {
+ -webkit-transform: perspective(200) translateZ(0px) rotateY(0deg);
+}
+.gallery li.focus ~ li {
+ -webkit-transform: perspective(200) translateZ(-70px) rotateY(-31deg);
+}
+
+.track { height: 14px; border: 1px solid #B3B3B3; margin: 10px 110px 0; background: none; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
+.liner { height: 12px; border: 1px solid #FEFEFE; background: #E0E0E0; opacity: .24; -moz-border-radius: 7px; -webkit-border-radius: 7px; border-radius: 7px; }
+.ui-slider { position: relative; text-align: left; border: none; border-left: 15px solid transparent; border-right: 15px solid transparent; background: none; margin: -14px 0 0; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; height: 14px; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; cursor: default; border: 1px solid #A7A7A7; border-top-color: #B3B3B3; background: #000 !important; top: 0; width: 30px; height: 14px; margin: -1px -16px !important; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
+.ui-slider .ui-slider-handle:focus { outline: 0; }
254 jquery.gallery.js
@@ -0,0 +1,254 @@
+// Define our templates.
+$.template('gallery.wrapper', '<ul class="gallery" style="width: ${width}px; height: ${height}px;">${content}</ul>');
+$.template('gallery.wrapperitem', '<li style="width: ${scaledwidth}px; height: ${scaledheight}px; border-bottom: ${scaledheight}px solid #000; margin-bottom: -${scaledheight}px; -webkit-transform-origin-y: ${transformOriginY}px;"><div class="item" style="width: ${scaledwidth}px; height: ${scaledheight};">{{html content}}</div></li>');
+$.template('gallery.skirt', '<div class="skirt" style="height: ${height}px;"><div class="track"><div class="liner"></div><div class="slider"></div></div></div>');
+
+(function( $ ) {
+ var selectors = {
+ gallery: '.gallery',
+ galleryitems: '.gallery li',
+ slider: '.slider',
+ skirt: '.skirt',
+ items: '.item'
+ }
+ var maxitemwidth, maxitemheight, galleryitemwidth, galleryheight;
+ var initialized = false;
+ var galleryitems = [];
+ var $current;
+
+ var settings = {
+ 'width-ratio' : 2.5,
+ 'height-ratio' : 1.5,
+ 'transform-origin-ratio' : .675,
+ 'first-margin-ratio' : .685,
+ 'subsequent-margin-ratio' : .13
+ };
+
+ // Does all the math to identify the correct math values.
+ function calculate() {
+ // 'this' is the jQuery object for the container.
+ maxitemwidth = this.width()/settings['width-ratio'];
+ maxitemheight = this.height()/settings['height-ratio'];
+
+ galleryitemwidth = maxitemwidth;
+ galleryheight = 0;
+
+ var length = galleryitems.length;
+
+ // Calculate gallery item width.
+ for (var i = 0; i < length; i++){
+ // Figure out which dimension is going to require the most resizing.
+ var scale = Math.min(maxitemwidth/galleryitems[i].width, maxitemheight/galleryitems[i].height, 1);
+
+ galleryitemwidth = $('body').width();
+ }
+
+ // Identify gallery item height now that we know the gallery item width.
+ for (var i = 0; i < length; i++){
+ // Figure out which dimension is going to require the most resizing.
+ var scale = galleryitemwidth / galleryitems[i].width;
+
+ galleryheight = $('body').height();
+ galleryitems[i].scaledwidth = $('body').width();
+ galleryitems[i].scaledheight = $('body').height();
+ }
+
+ // Now that we know the max height, figure out the transformation origin for each.
+ for (var i = 0; i < length; i++){
+ galleryitems[i].transformOriginY = galleryitems[i].scaledheight - galleryheight + (settings['transform-origin-ratio'] * galleryheight);
+ }
+
+ }
+
+ function draw() {
+ // Only runs once!
+ if (initialized) { return this; }
+ var $gallery = this;
+ initialized = true;
+
+ // Build the images array.
+ $items = this.find(selectors.items);
+
+ // Store gallery item information.
+ $items.each(function() {
+ $this = $(this);
+
+ galleryitems.push({ content: $this.html() });
+ });
+
+ // Do all of our calculations.
+ calculate.call(this);
+
+ // Build our HTML.
+ var gallerywrapper = $.tmpl('gallery.wrapper', { width: galleryitemwidth, height: galleryheight });
+ var content = $.tmpl('gallery.wrapperitem', galleryitems);
+ var skirt = $.tmpl('gallery.skirt', { height: galleryheight });
+
+ // Add in our HTML.
+ gallerywrapper.html(content);
+ this.html(gallerywrapper).append(skirt);
+
+ var startingpos = 0;
+
+ // Build the slider, set the starting value.
+ this.find(selectors.slider).slider({ max: $items.length-1, value: startingpos }).bind("slide", function(event, ui) {
+ $gallery.gallery('value', ui.value);
+ });
+
+ // Set the starting position to the first element.
+ this.gallery('value', startingpos);
+
+ return this;
+ }
+
+ var methods = {
+ init : function( options ) {
+ if (initialized) { return this; }
+
+ var $gallery = this;
+ $.extend( settings, options );
+
+ // Bind image clicks.
+ this.delegate(selectors.items, 'click', function(e) {
+ $gallery.gallery('value', $(this).closest('li'));
+ });
+
+ // Bind redraw to resize.
+ $(window).bind('resize', function() {
+ $gallery.gallery('redraw');
+ });
+
+ var $items = this.find(selectors.items);
+ var length = $items.length;
+
+ draw.call($gallery);
+
+ // Make sure the images are loaded before running draw.
+ // Following code from jquery.imagesLoaded.js
+ // mit license. paul irish. 2010.
+ /*
+ $items.bind('load', function() {
+ if (--length <= 0) { draw.call($gallery); }
+ }).each(function() {
+ if (this.complete || this.complete === undefined){
+ var src = this.src;
+ this.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
+ this.src = src;
+ }
+ });
+ */
+
+ return this;
+ },
+ redraw : function( ) {
+ // Do all of our calculations.
+ calculate.call(this);
+
+ // Reset container size.
+ this.find(selectors.gallery).css({ width: galleryitemwidth+'px', height: galleryheight+'px'});
+
+ // Disable transitions, reset each li to be the correct size, re-enable transitions.
+ this.find(selectors.galleryitems).css({ webkitTransition: 'none !important' }).each(function(i) {
+ $(this).css({ width: galleryitems[i].scaledwidth+'px', height: galleryitems[i].scaledheight+'px', borderBottom: galleryitems[i].scaledheight+'px solid #000', marginBottom: '-'+galleryitems[i].scaledheight+'px', webkitTransformOriginY: galleryitems[i].transformOriginY+'px' });
+ $(this).find(selectors.items).css({ width: galleryitems[i].scaledwidth, height: galleryitems[i].scaledheight });
+ }).css({ webkitTransition: '-webkit-transform .5s, left .5s' });
+
+ // Adjust skirt height.
+ this.find(selectors.skirt).css({ height: galleryheight+'px' });
+
+ // Set the focus back to where we were already.
+ this.gallery('value', $current[0]);
+
+ return this;
+ },
+ value : function( galleryitem ) {
+ if (typeof galleryitem == "number") {
+ galleryitem = this.find('li')[galleryitem];
+ } else if ( galleryitem == undefined ) {
+ // Read the property.
+ return $current.prevAll().length;
+ }
+
+ var $previous = $current;
+ var $galleryitem = $(galleryitem);
+
+ // Save the state globally.
+ $current = $galleryitem;
+
+ this.find(selectors.slider).slider('value', $galleryitem.prevAll().length);
+
+ if ($previous) {
+ $previous.removeClass('focus');
+ }
+ $galleryitem.addClass('focus');
+
+// $('#container').css({ zoom: 1 });
+
+ $galleryitem.prevAll().each(function(index) {
+ $(this).css({
+ left: (index * -settings['subsequent-margin-ratio'] * galleryitemwidth - settings['first-margin-ratio'] * galleryitemwidth)+'px',
+ zIndex: (galleryitems.length - (index + 1)).toString()
+ });
+ });
+ $galleryitem.css({
+ left: '0px',
+ zIndex: galleryitems.length.toString()
+ });
+ $galleryitem.nextAll().each(function(index) {
+ $(this).css({
+ left: (index * settings['subsequent-margin-ratio'] * galleryitemwidth + settings['first-margin-ratio'] * galleryitemwidth)+'px',
+ zIndex: (galleryitems.length - (index + 1)).toString()
+ });
+ });
+
+ return this;
+ },
+ prev : function( ) {
+ return methods[ 'adjust' ].call( this, -1 );
+ },
+ next : function( ) {
+ return methods[ 'adjust' ].call( this, 1 );
+ },
+ adjust : function( increment ) {
+ if (!$current) return this;
+ var direction = increment > 0;
+ increment = Math.abs(increment);
+
+ var image;
+
+ if (direction) {
+ // Look after.
+ var after = $current.nextAll();
+ image = after[increment-1];
+ } else {
+ // Look before.
+ var before = $current.prevAll();
+ image = before[increment-1];
+ }
+ if (image) {
+ return methods[ 'value' ].call( this, image );
+ } else {
+ return this;
+ }
+ }
+ };
+
+ $.fn.gallery = function( method ) {
+ // Method calling logic
+ if ( methods[method] ) {
+ return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
+ } else if ( typeof method === 'object' || ! method ) {
+ return methods.init.apply( this, arguments );
+ } else {
+ $.error( 'Method ' + method + ' does not exist on jQuery.gallery' );
+ }
+ };
+})( jQuery );
+
+// TODO: Add in buttons for horizontal scrollbar.
+// TODO: Support typical keyboard, mouse, and touch interactions.
+// TODO: Come up with animation for browsers that don't support 3D.
+// TODO: Add in loading animation for images.
+// TODO: Make templates adjustable by changing selectors to be defined by variables.
+// TODO: Debounce gallery resize.
+// TODO: Force absolute minimum sizes.

0 comments on commit e027716

Please sign in to comment.
Something went wrong with that request. Please try again.