/ Published in: JavaScript
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
var Panels = Class.create({ initialize: function(){ this.element = $(arguments[0]); this.element.identify(); if( !this.element ){ throw 'Panels: invalid contianer element' } this.element.setStyle({ overflow: 'hidden' }); this.element.makePositioned(); this.options = Object.extend({ force_horizontal: false, panel_selector: '.panel', only_children: false, start_index: 0, active_class: 'active', onInitialized: Prototype.emptyFunction, animation_scope: 'Panels'+this.element.identify(), animation: function(offsets){ return new Effect.Scroll( this.element, { x: offsets.left, y: offsets.top, mode: 'absolute', duration: 1.0, queue: {scope: this.options.animation_scope} }); } }, arguments[1] || {}); this.width_calculated = false; this.panels = this.options.only_children ? this.element.childElements().findAll( function(e){ return e.match(this.options.panel_selector); }.bind(this) ) : this.element.select(this.options.panel_selector); this.controls = { gotos: $H(), previous: $A(), next: $A() } this.initialize_controls(); if (this._calculate_width()) { this._finish(); } }, _finish: function(){ this._calculate_offsets(); this.goto_panel(this.options.start_index); this.options.onInitialized.call(this); }, _calculate_offsets: function(){ this.offsets = $H(); this.panels.each(function(p){ this.offsets.set(p.identify(), p.positionedOffset()); }, this); }, _calculate_width: function(force){ if( this.options.force_horizontal && (!this.width_calculated || force) ){ if( !this.container ){ // find the largest panel height this.force_horizontal_height = this.panels.map(function(p){ var position = p.getStyle('position'); p.setStyle({'position': 'absolute'}); var height = p.getHeight(); p.setStyle({'position': position}); return height; }).max(); this.container = new Element('div').setStyle({overflow: 'hidden', width: '100000px'}); this.panels.each(function(e){ this.container.insert(e.remove().setStyle({'float': 'left'})); }, this); this.element.insert(this.container); this.default_width = this.element.getWidth(); } var temp = new Element('div').setStyle({'float': 'left', 'width': '1px', 'height': '1px'}); this.panels.last().insert({after: temp}); return this._set_width(temp); } return true; }, _set_width: function( elm, finish){ var width = elm.positionedOffset()[0]; /* * if the scroll height of the container is greater than the maximum panel height, then all of the panels have not yet * been inserted into the container. or height container height has not been properly computed yet. */ if( (this.default_width && width <= this.default_width) || (this.force_horizontal_height && this.container.scrollHeight > this.force_horizontal_height)){ this._set_width.bind(this, elm, 1).defer(); return false; }else{ this.container.setStyle({width: width + 'px'}); this.width_calculated = true; elm.remove(); if( finish ){ this._finish(); }else{ return true; } } }, initialize_controls: function(){ var find = arguments[0] ? $(arguments[0]).select : $$; this.panels.each(function(p){ var gotos = find('a[href=#' + p.identify() + ']').invoke('observe', 'click', this.goto_panel.bindAsEventListener(this, p)); this.controls.gotos.set(p.identify(), (this.controls.gotos.get(p.identify) || $A()).concat(gotos)); }, this); var next = $$('a[href=#next].' + this.element.identify() + '_control[href=#next]').invoke('observe', 'click', this.next.bindAsEventListener(this)); this.controls.next = this.controls.next.concat(next); var previous = $$('a.' + this.element.identify() + '_control[href=#previous]').invoke('observe', 'click', this.previous.bindAsEventListener(this)); this.controls.previous = this.controls.previous.concat(previous); }, goto_panel: function(){ var elm = null; if( arguments.length > 1 ){ arguments[0].stop(); elm = arguments[1]; }else{ elm = arguments[0]; } var id = null; if (!Object.isString(elm)) { if( Object.isNumber(elm)){ elm = this.panels[parseInt(elm)]; } id = elm.identify(); }else{ id = elm; elm = $(id); } if( elm === this.current_panel ){ return; } var offsets = this.offsets.get(id); if( offsets ){ if (this.current_panel) { this.current_panel.removeClassName(this.options.active_class); this.controls.gotos.get(this.current_panel.identify()).invoke('removeClassName', this.options.active_class); } this.current_panel = elm; this.current_panel.addClassName(this.options.active_class); this.controls.gotos.get(this.current_panel.identify()).invoke('addClassName', this.options.active_class); try { this.options.animation.call(this, offsets); }catch(ex){ this.element.scrollTop = offsets.top; this.element.scrollLeft = offsets.left; } } }, next: function(){ if( arguments.length ){ arguments[0].stop(); } var index = this.panels.indexOf(this.current_panel) + 1; index = index > this.panels.length - 1 ? 0 : index; this.fire('panels:next', {panels: this.panels, index: index}); this.goto_panel(index); }, previous: function(){ if( arguments.length ){ arguments[0].stop(); } var index = this.panels.indexOf(this.current_panel) - 1; index = index < 0 ? this.panels.length - 1 : index; this.fire('panels:previous', {panels: this.panels, index: index}); this.goto_panel(index); }, observe: function(){ this.element.observe.apply(this.element, arguments); }, fire: function(){ this.element.fire.apply(this.element, arguments); }, destroy: function(){ this.controls.previous.concat(this.controls.next).concat(this.controls.gotos.values().flatten()).invoke('stopObserving'); } });