1/*************************************************! 2* 3* project: liteAccordion - a horizontal accordion plugin for jQuery 4* author: Nicola Hibbert 5* url: http://nicolahibbert.com/liteaccordion-v2/ 6* demo: http://www.nicolahibbert.com/demo/liteAccordion/ 7* 8* Version: 2.0.1 9* Copyright: (c) 2010-2011 Nicola Hibbert 10* Licence: MIT 11* 12**************************************************/ 13 14;(function($) { 15 16 var LiteAccordion = function(elem, options) { 17 18 var defaults = { 19 containerWidth : 960, // fixed (px) 20 containerHeight : 320, // fixed (px) 21 headerWidth: 48, // fixed (px) 22 23 activateOn : 'click', // click or mouseover 24 firstSlide : 1, // displays slide (n) on page load 25 slideSpeed : 800, // slide animation speed 26 onTriggerSlide : function() {}, // callback on slide activate 27 onSlideAnimComplete : function() {}, // callback on slide anim complete 28 29 autoPlay : false, // automatically cycle through slides 30 pauseOnHover : false, // pause on hover 31 cycleSpeed : 6000, // time between slide cycles 32 easing : 'swing', // custom easing function 33 34 theme : 'basic', // basic, dark, light, or stitch 35 rounded : false, // square or rounded corners 36 enumerateSlides : false, // put numbers on slides 37 linkable : false // link slides via hash 38 }, 39 40 // merge defaults with options in new settings object 41 settings = $.extend({}, defaults, options), 42 43 // 'globals' 44 slides = elem.children('ol').children('li'), 45 header = slides.children(':first-child'), 46 slideLen = slides.length, 47 slideWidth = settings.containerWidth - slideLen * settings.headerWidth, 48 49 // public methods 50 methods = { 51 52 // start elem animation 53 play : function(index) { 54 var next = core.nextSlide(index && index); 55 56 if (core.playing) return; 57 58 // start autoplay 59 core.playing = setInterval(function() { 60 header.eq(next()).trigger('click.liteAccordion'); 61 }, settings.cycleSpeed); 62 }, 63 64 // stop elem animation 65 stop : function() { 66 clearInterval(core.playing); 67 core.playing = 0; 68 }, 69 70 // trigger next slide 71 next : function() { 72 methods.stop(); 73 74 header.eq(core.currentSlide === slideLen - 1 ? 0 : core.currentSlide + 1).trigger('click.liteAccordion'); 75 }, 76 77 // trigger previous slide 78 prev : function() { 79 methods.stop(); 80 header.eq(core.currentSlide - 1).trigger('click.liteAccordion'); 81 }, 82 83 // destroy plugin instance 84 destroy : function() { 85 // stop autoplay 86 methods.stop(); 87 88 // remove hashchange event bound to window 89 $(window).unbind('.liteAccordion'); 90 91 // remove generated styles, classes, data, events 92 elem 93 .attr('style', '') 94 .removeClass('accordion basic dark light stitch') 95 .removeData('liteAccordion') 96 .unbind('.liteAccordion') 97 .find('li > :first-child') 98 .unbind('.liteAccordion') 99 .filter('.selected') 100 .removeClass('selected') 101 .end() 102 .find('b') 103 .remove(); 104 105 slides 106 .removeClass('slide') 107 .children() 108 .attr('style', ''); 109 }, 110 111 // poke around the internals (NOT CHAINABLE) 112 debug : function() { 113 return { 114 elem : elem, 115 defaults : defaults, 116 settings : settings, 117 methods : methods, 118 core : core 119 }; 120 } 121 }, 122 123 // core utility and animation methods 124 core = { 125 126 // set style properties 127 setStyles : function() { 128 // set container heights, widths, theme & corner style 129 elem 130 .width(settings.containerWidth) 131 .height(settings.containerHeight) 132 .addClass('accordion') 133 .addClass(settings.rounded && 'rounded') 134 .addClass(settings.theme); 135 136 // set tab width, height and selected class 137 slides 138 .addClass('slide') 139 .children(':first-child') 140 .width(settings.containerHeight) 141 .height(settings.headerWidth) 142 .eq(settings.firstSlide - 1) 143 .addClass('selected'); 144 145 // set initial positions for each slide 146 header.each(function(index) { 147 var $this = $(this), 148 left = index * settings.headerWidth, 149 margin = header.first().next(), 150 offset = parseInt(margin.css('marginLeft'), 10) || parseInt(margin.css('marginRight'), 10); 151 152 if (index >= settings.firstSlide) left += slideWidth; 153 154 $this 155 .css('left', left) 156 .next() 157 .width(slideWidth - offset) 158 .css({ left : left, paddingLeft : settings.headerWidth }); 159 160 // add number to bottom of tab 161 settings.enumerateSlides && $this.append('<b>' + (index + 1) + '</b>'); 162 163 }); 164 }, 165 166 // bind click and mouseover events 167 bindEvents : function() { 168 if (settings.activateOn === 'click') { 169 header.bind('click.liteAccordion', core.triggerSlide); 170 } else if (settings.activateOn === 'mouseover') { 171 header.bind({ 172 'mouseover.liteAccordion' : core.triggerSlide, 173 'click.liteAccordion' : core.triggerSlide 174 }); 175 } 176 177 // pause on hover (can't use custom events with $.hover()) 178 if (settings.pauseOnHover && settings.autoPlay) { 179 elem.bind('mouseover.liteAccordion', function() { 180 core.playing && methods.stop(); 181 }).bind('mouseout.liteAccordion', function() { 182 !core.playing && methods.play(core.currentSlide); 183 }); 184 } 185 }, 186 187 linkable : function() { 188 var cacheSlideNames = (function() { 189 var slideNames = []; 190 191 slides.each(function() { 192 if ($(this).attr('name')) slideNames.push(($(this).attr('name')).toLowerCase()); 193 }); 194 195 // memoize 196 return cacheSlideNames = slideNames; 197 })(); 198 199 var triggerHash = function(e) { 200 var index; 201 202 if (e.type === 'load' && !window.location.hash) return;
203 if (e.type === 'hashchange' && core.playing) return; 204 205 index = $.inArray((window.location.hash.slice(1)).toLowerCase(), cacheSlideNames); 206 if (index > -1 && index < cacheSlideNames.length) header.eq(index).trigger('click.liteAccordion'); 207 }; 208 209 $(window).bind({ 210 'hashchange.liteAccordion' : triggerHash, 211 'load.liteAccordion' : triggerHash 212 }); 213 }, 214 215 // counter for autoPlay (zero index firstSlide on init) 216 currentSlide : settings.firstSlide - 1, 217 218 // next slide index 219 nextSlide : function(index) { 220 var next = index + 1 || core.currentSlide + 1; 221 222 // closure 223 return function() { 224 return next++ % slideLen; 225 }; 226 }, 227 228 // holds interval counter 229 playing : 0, 230 231 // animates left and right groups of slides 232 // side: denotes left side 233 animSlideGroup : function(index, next, side) { 234 var filterExpr = side ? ':lt(' + (index + 1) + ')' : ':gt(' + index + ')'; 235 236 slides 237 .filter(filterExpr) 238 .each(function() { 239 var $this = $(this), 240 slideIndex = slides.index($this); 241 242 $this 243 .children() 244 .stop(true) 245 .animate({ 246 left : (side ? 0 : slideWidth) + slideIndex * settings.headerWidth 247 }, 248 settings.slideSpeed, 249 settings.easing, 250 function() { 251 // flag ensures that fn is only called one time per triggerSlide 252 if (!core.slideAnimCompleteFlag) { 253 settings.onSlideAnimComplete.call(next); 254 core.slideAnimCompleteFlag = true; 255 } 256 }); 257 }); 258 }, 259 260 slideAnimCompleteFlag : false, 261 262 // trigger slide animation 263 triggerSlide : function(e) { 264 var $this = $(this), 265 index = header.index($this), 266 next = $this.next(); 267 268 // update core.currentSlide 269 core.currentSlide = index; 270 271 // reset onSlideAnimComplete callback flag 272 core.slideAnimCompleteFlag = false; 273 274 // remove, then add selected class 275 header.removeClass('selected').filter($this).addClass('selected'); 276 277 // reset current slide index in core.nextSlide closure 278 if (e.originalEvent && settings.autoPlay) { 279 methods.stop(); 280 methods.play(index); 281 } 282 283 // set location.hash 284 if (settings.linkable && !core.playing) window.location.hash = $this.parent().attr('name'); 285 286 // trigger callback in context of sibling div 287 settings.onTriggerSlide.call(next); 288 289 // animate left & right groups 290 core.animSlideGroup(index, next, true); 291 core.animSlideGroup(index, next); 292 }, 293 294 ieClass : function() { 295 var version = +($.browser.version).charAt(0); 296 297 if (version < 7) methods.destroy(); 298 if (version === 7 || version === 8) { 299 slides.each(function(index) { 300 $(this).addClass('slide-' + index); 301 }); 302 } 303 304 elem.addClass('ie ie' + version); 305 }, 306 307 init : function() { 308 // test for ie 309 if ($.browser.msie) core.ieClass(); 310 311 // init styles and events 312 core.setStyles(); 313 core.bindEvents(); 314 315 // check slide speed is not faster than cycle speed 316 if (settings.cycleSpeed < settings.slideSpeed) settings.cycleSpeed = settings.slideSpeed; 317 318 // init hash links 319 if (settings.linkable && 'onhashchange' in window) core.linkable(); 320 321 // init autoplay 322 settings.autoPlay && methods.play(); 323 } 324 }; 325 326 // init plugin
327 core.init(); 328 329 // expose methods 330 return methods; 331 332 }; 333 334 $.fn.liteAccordion = function(method) { 335 var elem = this, 336 instance = elem.data('liteAccordion'); 337 338 // if creating a new instance 339 if (typeof method === 'object' || !method) { 340 return elem.each(function() { 341 var liteAccordion; 342 343 // if plugin already instantiated, return 344 if (instance) return; 345 346 // otherwise create a new instance 347 liteAccordion = new LiteAccordion(elem, method); 348 elem.data('liteAccordion', liteAccordion); 349 }); 350 351 // otherwise, call method on current instance 352 } else if (typeof method === 'string' && instance[method]) { 353 // debug method isn't chainable b/c we need the debug object to be returned 354 if (method === 'debug') { 355 return instance[method].call(elem); 356 } else { // the rest of the methods are chainable though 357 instance[method].call(elem); 358 return elem; 359 } 360 } 361 }; 362 363})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.