new pheno download tests pass
[sgn.git] / js / unslider.js
blob40c65c3e9c97367de97f63290169ad092f0d3b50
1 /**\r
2  *   Unslider by @idiot\r
3  */\r
4  \r
5 (function($, f) {\r
6         //  If there's no jQuery, Unslider can't work, so kill the operation.\r
7         if(!$) return f;\r
8         \r
9         var Unslider = function() {\r
10                 //  Set up our elements\r
11                 this.el = f;\r
12                 this.items = f;\r
13                 \r
14                 //  Dimensions\r
15                 this.sizes = [];\r
16                 this.max = [0,0];\r
17                 \r
18                 //  Current inded\r
19                 this.current = 0;\r
20                 \r
21                 //  Start/stop timer\r
22                 this.interval = f;\r
23                                 \r
24                 //  Set some options\r
25                 this.opts = {\r
26                         speed: 500,\r
27                         delay: 3000, // f for no autoplay\r
28                         complete: f, // when a slide's finished\r
29                         keys: !f, // keyboard shortcuts - disable if it breaks things\r
30                         dots: f, // display ••••o• pagination\r
31                         fluid: f // is it a percentage width?,\r
32                 };\r
33                 \r
34                 //  Create a deep clone for methods where context changes\r
35                 var _ = this;\r
37                 this.init = function(el, opts) {\r
38                         this.el = el;\r
39                         this.ul = el.children('ul');\r
40                         this.max = [el.outerWidth(), el.outerHeight()];                 \r
41                         this.items = this.ul.children('li').each(this.calculate);\r
42                         \r
43                         //  Check whether we're passing any options in to Unslider\r
44                         this.opts = $.extend(this.opts, opts);\r
45                         \r
46                         //  Set up the Unslider\r
47                         this.setup();\r
48                         \r
49                         return this;\r
50                 };\r
51                 \r
52                 //  Get the width for an element\r
53                 //  Pass a jQuery element as the context with .call(), and the index as a parameter: Unslider.calculate.call($('li:first'), 0)\r
54                 this.calculate = function(index) {\r
55                         var me = $(this),\r
56                                 width = me.outerWidth(), height = me.outerHeight();\r
57                         \r
58                         //  Add it to the sizes list\r
59                         _.sizes[index] = [width, height];\r
60                         \r
61                         //  Set the max values\r
62                         if(width > _.max[0]) _.max[0] = width;\r
63                         if(height > _.max[1]) _.max[1] = height;\r
64                 };\r
65                 \r
66                 //  Work out what methods need calling\r
67                 this.setup = function() {\r
68                         //  Set the main element\r
69                         this.el.css({\r
70                                 overflow: 'hidden',\r
71                                 width: _.max[0],\r
72                                 height: this.items.first().outerHeight()\r
73                         });\r
74                         \r
75                         //  Set the relative widths\r
76                         this.ul.css({width: (this.items.length * 100) + '%', position: 'relative'});\r
77                         this.items.css('width', (100 / this.items.length) + '%');\r
78                         \r
79                         if(this.opts.delay !== f) {\r
80                                 this.start();\r
81                                 this.el.hover(this.stop, this.start);\r
82                         }\r
83                         \r
84                         //  Custom keyboard support\r
85                         this.opts.keys && $(document).keydown(this.keys);\r
86                         \r
87                         //  Dot pagination\r
88                         this.opts.dots && this.dots();\r
89                         \r
90                         //  Little patch for fluid-width sliders. Screw those guys.\r
91                         if(this.opts.fluid) {\r
92                                 var resize = function() {\r
93                                         _.el.css('width', Math.min(Math.round((_.el.outerWidth() / _.el.parent().outerWidth()) * 100), 100) + '%');\r
94                                 };\r
95                                 \r
96                                 resize();\r
97                                 $(window).resize(resize);\r
98                         }\r
99                         \r
100                         if(this.opts.arrows) {\r
101                                 this.el.parent().append('<p class="arrows"><span class="prev">←</span><span class="next">→</span></p>')\r
102                                         .find('.arrows span').click(function() {\r
103                                                 $.isFunction(_[this.className]) && _[this.className]();\r
104                                         });\r
105                         };\r
106                         \r
107                         //  Swipe support\r
108                         if($.event.swipe) {\r
109                                 this.el.on('swipeleft', _.prev).on('swiperight', _.next);\r
110                         }\r
111                 };\r
112                 \r
113                 //  Move Unslider to a slide index\r
114                 this.move = function(index, cb) {\r
115                         //  If it's out of bounds, go to the first slide\r
116                         if(!this.items.eq(index).length) index = 0;\r
117                         if(index < 0) index = (this.items.length - 1);\r
118                         \r
119                         var target = this.items.eq(index);\r
120                         var obj = {height: target.outerHeight()};\r
121                         var speed = cb ? 5 : this.opts.speed;\r
122                         \r
123                         if(!this.ul.is(':animated')) {                  \r
124                                 //  Handle those pesky dots\r
125                                 _.el.find('.dot:eq(' + index + ')').addClass('active').siblings().removeClass('active');\r
127                                 this.el.animate(obj, speed) && this.ul.animate($.extend({left: '-' + index + '00%'}, obj), speed, function(data) {\r
128                                         _.current = index;\r
129                                         $.isFunction(_.opts.complete) && !cb && _.opts.complete(_.el);\r
130                                 });\r
131                         }\r
132                 };\r
133                 \r
134                 //  Autoplay functionality\r
135                 this.start = function() {\r
136                         _.interval = setInterval(function() {\r
137                                 _.move(_.current + 1);\r
138                         }, _.opts.delay);\r
139                 };\r
140                 \r
141                 //  Stop autoplay\r
142                 this.stop = function() {\r
143                         _.interval = clearInterval(_.interval);\r
144                         return _;\r
145                 };\r
146                 \r
147                 //  Keypresses\r
148                 this.keys = function(e) {\r
149                         var key = e.which;\r
150                         var map = {\r
151                                 //  Prev/next\r
152                                 37: _.prev,\r
153                                 39: _.next,\r
154                                 \r
155                                 //  Esc\r
156                                 27: _.stop\r
157                         };\r
158                         \r
159                         if($.isFunction(map[key])) {\r
160                                 map[key]();\r
161                         }\r
162                 };\r
163                 \r
164                 //  Arrow navigation\r
165                 this.next = function() { return _.stop().move(_.current + 1) };\r
166                 this.prev = function() { return _.stop().move(_.current - 1) };\r
167                 \r
168                 this.dots = function() {\r
169                         //  Create the HTML\r
170                         var html = '<ol class="dots">';\r
171                                 $.each(this.items, function(index) { html += '<li class="dot' + (index < 1 ? ' active' : '') + '">' + (index + 1) + '</li>'; });\r
172                                 html += '</ol>';\r
173                         \r
174                         //  Add it to the Unslider\r
175                         this.el.addClass('has-dots').append(html).find('.dot').click(function() {\r
176                                 _.move($(this).index());\r
177                         });\r
178                 };\r
179         };\r
180         \r
181         //  Create a jQuery plugin\r
182         $.fn.unslider = function(o) {\r
183                 var len = this.length;\r
184                 \r
185                 //  Enable multiple-slider support\r
186                 return this.each(function(index) {\r
187                         //  Cache a copy of $(this), so it \r
188                         var me = $(this);\r
189                         var instance = (new Unslider).init(me, o);\r
190                         \r
191                         //  Invoke an Unslider instance\r
192                         me.data('unslider' + (len > 1 ? '-' + (index + 1) : ''), instance);\r
193                 });\r
194         };\r
195 })(window.jQuery, false);