1 // Layout container to handle one container with lm_left, lm_right, lm_top, lm_bottom, and lm_center 2 rio.LayoutContainer = Class.create({ 3 initialize: function(root) { 4 this.parent = $(root.parentNode); 5 root.setStyle("padding:0; margin:0; border:0"); 6 // Pre-compute paddings 7 $w("top left right bottom").each(function(key) { 8 this.parent[key] = this.padding(this.parent, key); 9 }.bind(this)); 10 11 // Init arrays 12 $w("lm_top lm_left lm_right lm_bottom lm_center").each(function(key) { 13 this[key] = []; 14 }.bind(this)); 15 16 root.childElements().each(function(element) { 17 element.style.position = "absolute"; 18 element.paddingWidth = this.fullPadding(element, "left") + this.fullPadding(element, "right"); 19 element.paddingHeight = this.fullPadding(element, "top") + this.fullPadding(element, "bottom"); 20 element.marginWidth = this.margin(element, "left") + this.margin(element, "right"); 21 element.marginHeight = this.margin(element, "top") + this.margin(element, "bottom"); 22 23 if (element.hasClassName("lm_top")) { 24 this.lm_top.push(element); 25 } else if (element.hasClassName("lm_left")) { 26 this.lm_left.push(element); 27 } else if (element.hasClassName("lm_right")) { 28 this.lm_right.unshift(element); 29 } else if (element.hasClassName("lm_bottom")) { 30 this.lm_bottom.unshift(element); 31 } else if (element.hasClassName("lm_center")) { 32 if (this.lm_center.length > 0) { 33 throw("Only one lm_center per lm_container"); 34 } 35 this.lm_center.push(element); 36 } 37 }.bind(this)); 38 }, 39 40 updateSize: function() { 41 var d = this.parent.getDimensions(); 42 var w = d.width - this.parent.left - this.border(this.parent, "left") - this.border(this.parent, "right"); 43 var h = d.height - this.parent.top - this.parent.bottom - this.border(this.parent, "top") - this.border(this.parent, "bottom"); 44 var that = this; // To avoid too many binds 45 46 // Set position and size of all top elements 47 var top = this.parent.top; 48 this.lm_top.each(function(element) { 49 var s = element.style; 50 that.setPositivePxValue(s, 'width', w - element.paddingWidth); 51 s.top = top + "px"; 52 top += element.getHeight() + element.marginHeight; 53 }); 54 h -= top - this.parent.top; 55 56 // Set position and size of all bottom elements 57 var bottom = this.parent.bottom; 58 this.lm_bottom.each(function(element) { 59 var s = element.style; 60 that.setPositivePxValue(s, 'width', w - element.paddingWidth); 61 s.bottom = bottom + "px"; 62 bottom += element.getHeight() + element.marginHeight; 63 }); 64 h -= bottom - this.parent.bottom; 65 66 // Set position and size of all left elements 67 var left = this.parent.left; 68 this.lm_left.each(function(element) { 69 var s = element.style; 70 that.setPositivePxValue(s, 'height', h - element.paddingHeight); 71 s.top = top + "px"; 72 s.left = left + "px"; 73 left += element.getWidth() + element.marginWidth; 74 }); 75 w -= left; 76 77 // Set position and size of all right elements 78 var right = this.parent.right; 79 this.lm_right.each(function(element) { 80 var s = element.style; 81 that.setPositivePxValue(s, 'height', h - element.paddingHeight); 82 s.top = top + "px"; 83 s.right = right + "px"; 84 right += element.getWidth() + element.marginWidth; 85 }); 86 w -= right; 87 88 // Set position and size of all center elements 89 // Only one center for this version 90 var center = this.lm_center.first(); 91 var s = center.style; 92 s.top = top + "px"; 93 s.left = left + "px"; 94 this.setPositivePxValue(s, 'width', w - center.paddingWidth); 95 this.setPositivePxValue(s, 'height', h - center.paddingHeight); 96 }, 97 98 // Private functions 99 fullPadding: function(element, s) { 100 return this.padding(element, s) + this.border(element, s) + this.margin(element, s); 101 }, 102 103 border: function(element, s) { 104 var border = parseInt(element.getStyle("border-" + s + "-width") || 0, 10); 105 if (isNaN(border)) { // Test for IE!! 106 border = 0; 107 } 108 return border; 109 }, 110 111 padding: function(element, s) { 112 var padding = parseInt(element.getStyle("padding-" + s) || 0, 10); 113 if (isNaN(padding)) { // Test for IE!! 114 padding = 0; 115 } 116 return padding; 117 }, 118 119 margin: function(element, s) { 120 var margin = parseInt(element.getStyle("margin-" + s) || 0, 10); 121 if (isNaN(margin)) { // Test for IE!! 122 margin = 0; 123 } 124 return margin; 125 }, 126 127 setPositivePxValue:function(objet, key, value) { 128 objet[key] = (value > 0 ? value : 0) + "px"; 129 } 130 }); 131 132 // Layout manager: handles N layout container 133 rio.LayoutManager = Class.create({ 134 initialize: function(root) { 135 this.root = root || document.body; 136 this.init(); 137 Event.observe(window, "resize", this.resize.bind(this)); 138 }, 139 140 reset: function() { 141 this.init.bind(this).defer(); 142 }, 143 144 add: function(root) { 145 this.addElement.bind(this, root, true).defer(); 146 }, 147 148 // Private functions 149 init: function() { 150 this.containers = []; 151 this.addElement(this.root); 152 this.resize(); 153 }, 154 155 resize: function() { 156 this.containers.invoke("updateSize"); 157 }, 158 159 addElement: function(element, doResize) { 160 $(element).getElementsBySelector(".lm_container").each(function(element) { 161 this.containers.push(new rio.LayoutContainer(element)); 162 }.bind(this)); 163 if (doResize) { 164 this.resize(); 165 } 166 } 167 }); 168