Prototype.js Panels


/ Published in: JavaScript
Save to your folder(s)



Copy this code and paste it in your HTML
  1. var Panels = Class.create({
  2. initialize: function(){
  3. this.element = $(arguments[0]);
  4. this.element.identify();
  5. if( !this.element ){
  6. throw 'Panels: invalid contianer element'
  7. }
  8. this.element.setStyle({
  9. overflow: 'hidden'
  10. });
  11. this.element.makePositioned();
  12. this.options = Object.extend({
  13. force_horizontal: false,
  14. panel_selector: '.panel',
  15. only_children: false,
  16. start_index: 0,
  17. active_class: 'active',
  18. onInitialized: Prototype.emptyFunction,
  19. animation_scope: 'Panels'+this.element.identify(),
  20. animation: function(offsets){
  21. return new Effect.Scroll( this.element, {
  22. x: offsets.left,
  23. y: offsets.top,
  24. mode: 'absolute',
  25. duration: 1.0,
  26. queue: {scope: this.options.animation_scope}
  27. });
  28. }
  29. }, arguments[1] || {});
  30. this.width_calculated = false;
  31. this.panels =
  32. this.options.only_children ?
  33. this.element.childElements().findAll( function(e){
  34. return e.match(this.options.panel_selector);
  35. }.bind(this) ) :
  36. this.element.select(this.options.panel_selector);
  37.  
  38. this.controls = {
  39. gotos: $H(),
  40. previous: $A(),
  41. next: $A()
  42. }
  43.  
  44. this.initialize_controls();
  45. if (this._calculate_width()) {
  46. this._finish();
  47. }
  48. },
  49. _finish: function(){
  50. this._calculate_offsets();
  51. this.goto_panel(this.options.start_index);
  52. this.options.onInitialized.call(this);
  53. },
  54. _calculate_offsets: function(){
  55. this.offsets = $H();
  56. this.panels.each(function(p){
  57. this.offsets.set(p.identify(), p.positionedOffset());
  58. }, this);
  59. },
  60. _calculate_width: function(force){
  61. if( this.options.force_horizontal && (!this.width_calculated || force) ){
  62. if( !this.container ){
  63. // find the largest panel height
  64. this.force_horizontal_height = this.panels.map(function(p){
  65. var position = p.getStyle('position');
  66. p.setStyle({'position': 'absolute'});
  67. var height = p.getHeight();
  68. p.setStyle({'position': position});
  69. return height;
  70. }).max();
  71. this.container = new Element('div').setStyle({overflow: 'hidden', width: '100000px'});
  72. this.panels.each(function(e){
  73. this.container.insert(e.remove().setStyle({'float': 'left'}));
  74. }, this);
  75. this.element.insert(this.container);
  76. this.default_width = this.element.getWidth();
  77. }
  78. var temp = new Element('div').setStyle({'float': 'left', 'width': '1px', 'height': '1px'});
  79. this.panels.last().insert({after: temp});
  80. return this._set_width(temp);
  81. }
  82. return true;
  83. },
  84. _set_width: function( elm, finish){
  85. var width = elm.positionedOffset()[0];
  86. /*
  87. * if the scroll height of the container is greater than the maximum panel height, then all of the panels have not yet
  88. * been inserted into the container. or height container height has not been properly computed yet.
  89. */
  90. if( (this.default_width && width <= this.default_width) || (this.force_horizontal_height && this.container.scrollHeight > this.force_horizontal_height)){
  91. this._set_width.bind(this, elm, 1).defer();
  92. return false;
  93. }else{
  94. this.container.setStyle({width: width + 'px'});
  95. this.width_calculated = true;
  96. elm.remove();
  97. if( finish ){
  98. this._finish();
  99. }else{
  100. return true;
  101. }
  102. }
  103. },
  104. initialize_controls: function(){
  105. var find = arguments[0] ? $(arguments[0]).select : $$;
  106. this.panels.each(function(p){
  107. var gotos = find('a[href=#' + p.identify() + ']').invoke('observe', 'click', this.goto_panel.bindAsEventListener(this, p));
  108. this.controls.gotos.set(p.identify(), (this.controls.gotos.get(p.identify) || $A()).concat(gotos));
  109. }, this);
  110. var next = $$('a[href=#next].' + this.element.identify() + '_control[href=#next]').invoke('observe', 'click', this.next.bindAsEventListener(this));
  111. this.controls.next = this.controls.next.concat(next);
  112. var previous = $$('a.' + this.element.identify() + '_control[href=#previous]').invoke('observe', 'click', this.previous.bindAsEventListener(this));
  113. this.controls.previous = this.controls.previous.concat(previous);
  114. },
  115. goto_panel: function(){
  116. var elm = null;
  117. if( arguments.length > 1 ){
  118. arguments[0].stop();
  119. elm = arguments[1];
  120. }else{
  121. elm = arguments[0];
  122. }
  123. var id = null;
  124. if (!Object.isString(elm)) {
  125. if( Object.isNumber(elm)){
  126. elm = this.panels[parseInt(elm)];
  127. }
  128. id = elm.identify();
  129. }else{
  130. id = elm;
  131. elm = $(id);
  132. }
  133. if( elm === this.current_panel ){
  134. return;
  135. }
  136. var offsets = this.offsets.get(id);
  137. if( offsets ){
  138. if (this.current_panel) {
  139. this.current_panel.removeClassName(this.options.active_class);
  140. this.controls.gotos.get(this.current_panel.identify()).invoke('removeClassName', this.options.active_class);
  141. }
  142. this.current_panel = elm;
  143. this.current_panel.addClassName(this.options.active_class);
  144. this.controls.gotos.get(this.current_panel.identify()).invoke('addClassName', this.options.active_class);
  145. try {
  146. this.options.animation.call(this, offsets);
  147. }catch(ex){
  148. this.element.scrollTop = offsets.top;
  149. this.element.scrollLeft = offsets.left;
  150. }
  151. }
  152. },
  153. next: function(){
  154. if( arguments.length ){
  155. arguments[0].stop();
  156. }
  157. var index = this.panels.indexOf(this.current_panel) + 1;
  158. index = index > this.panels.length - 1 ? 0 : index;
  159. this.fire('panels:next', {panels: this.panels, index: index});
  160. this.goto_panel(index);
  161. },
  162. previous: function(){
  163. if( arguments.length ){
  164. arguments[0].stop();
  165. }
  166. var index = this.panels.indexOf(this.current_panel) - 1;
  167. index = index < 0 ? this.panels.length - 1 : index;
  168. this.fire('panels:previous', {panels: this.panels, index: index});
  169. this.goto_panel(index);
  170. },
  171. observe: function(){
  172. this.element.observe.apply(this.element, arguments);
  173. },
  174. fire: function(){
  175. this.element.fire.apply(this.element, arguments);
  176. },
  177. destroy: function(){
  178. this.controls.previous.concat(this.controls.next).concat(this.controls.gotos.values().flatten()).invoke('stopObserving');
  179. }
  180. });

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.