|
1 /*** |
|
2 |
|
3 MochiKit.Style 1.4 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 if (typeof(dojo) != 'undefined') { |
|
12 dojo.provide('MochiKit.Style'); |
|
13 dojo.require('MochiKit.Base'); |
|
14 dojo.require('MochiKit.DOM'); |
|
15 } |
|
16 if (typeof(JSAN) != 'undefined') { |
|
17 JSAN.use('MochiKit.Base', []); |
|
18 JSAN.use('MochiKit.DOM', []); |
|
19 } |
|
20 |
|
21 try { |
|
22 if (typeof(MochiKit.Base) == 'undefined') { |
|
23 throw ''; |
|
24 } |
|
25 } catch (e) { |
|
26 throw 'MochiKit.Style depends on MochiKit.Base!'; |
|
27 } |
|
28 |
|
29 try { |
|
30 if (typeof(MochiKit.DOM) == 'undefined') { |
|
31 throw ''; |
|
32 } |
|
33 } catch (e) { |
|
34 throw 'MochiKit.Style depends on MochiKit.DOM!'; |
|
35 } |
|
36 |
|
37 |
|
38 if (typeof(MochiKit.Style) == 'undefined') { |
|
39 MochiKit.Style = {}; |
|
40 } |
|
41 |
|
42 MochiKit.Style.NAME = 'MochiKit.Style'; |
|
43 MochiKit.Style.VERSION = '1.4'; |
|
44 MochiKit.Style.__repr__ = function () { |
|
45 return '[' + this.NAME + ' ' + this.VERSION + ']'; |
|
46 }; |
|
47 MochiKit.Style.toString = function () { |
|
48 return this.__repr__(); |
|
49 }; |
|
50 |
|
51 MochiKit.Style.EXPORT_OK = []; |
|
52 |
|
53 MochiKit.Style.EXPORT = [ |
|
54 'setStyle', |
|
55 'setOpacity', |
|
56 'getStyle', |
|
57 'getElementDimensions', |
|
58 'elementDimensions', // deprecated |
|
59 'setElementDimensions', |
|
60 'getElementPosition', |
|
61 'elementPosition', // deprecated |
|
62 'setElementPosition', |
|
63 'setDisplayForElement', |
|
64 'hideElement', |
|
65 'showElement', |
|
66 'getViewportDimensions', |
|
67 'getViewportPosition', |
|
68 'Dimensions', |
|
69 'Coordinates' |
|
70 ]; |
|
71 |
|
72 |
|
73 /* |
|
74 |
|
75 Dimensions |
|
76 |
|
77 */ |
|
78 /** @id MochiKit.Style.Dimensions */ |
|
79 MochiKit.Style.Dimensions = function (w, h) { |
|
80 this.w = w; |
|
81 this.h = h; |
|
82 }; |
|
83 |
|
84 MochiKit.Style.Dimensions.prototype.__repr__ = function () { |
|
85 var repr = MochiKit.Base.repr; |
|
86 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}'; |
|
87 }; |
|
88 |
|
89 MochiKit.Style.Dimensions.prototype.toString = function () { |
|
90 return this.__repr__(); |
|
91 }; |
|
92 |
|
93 |
|
94 /* |
|
95 |
|
96 Coordinates |
|
97 |
|
98 */ |
|
99 /** @id MochiKit.Style.Coordinates */ |
|
100 MochiKit.Style.Coordinates = function (x, y) { |
|
101 this.x = x; |
|
102 this.y = y; |
|
103 }; |
|
104 |
|
105 MochiKit.Style.Coordinates.prototype.__repr__ = function () { |
|
106 var repr = MochiKit.Base.repr; |
|
107 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}'; |
|
108 }; |
|
109 |
|
110 MochiKit.Style.Coordinates.prototype.toString = function () { |
|
111 return this.__repr__(); |
|
112 }; |
|
113 |
|
114 |
|
115 MochiKit.Base.update(MochiKit.Style, { |
|
116 |
|
117 /** @id MochiKit.Style.getStyle */ |
|
118 getStyle: function (elem, cssProperty) { |
|
119 var dom = MochiKit.DOM; |
|
120 var d = dom._document; |
|
121 |
|
122 elem = dom.getElement(elem); |
|
123 cssProperty = MochiKit.Base.camelize(cssProperty); |
|
124 |
|
125 if (!elem || elem == d) { |
|
126 return undefined; |
|
127 } |
|
128 if (cssProperty == 'opacity' && elem.filters) { |
|
129 var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/); |
|
130 if (opacity && opacity[1]) { |
|
131 return parseFloat(opacity[1]) / 100; |
|
132 } |
|
133 return 1.0; |
|
134 } |
|
135 var value = elem.style ? elem.style[cssProperty] : null; |
|
136 if (!value) { |
|
137 if (d.defaultView && d.defaultView.getComputedStyle) { |
|
138 var css = d.defaultView.getComputedStyle(elem, null); |
|
139 cssProperty = cssProperty.replace(/([A-Z])/g, '-$1' |
|
140 ).toLowerCase(); // from dojo.style.toSelectorCase |
|
141 value = css ? css.getPropertyValue(cssProperty) : null; |
|
142 } else if (elem.currentStyle) { |
|
143 value = elem.currentStyle[cssProperty]; |
|
144 } |
|
145 } |
|
146 if (cssProperty == 'opacity') { |
|
147 value = parseFloat(value); |
|
148 } |
|
149 |
|
150 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) { |
|
151 if (MochiKit.Style.getStyle(elem, 'position') == 'static') { |
|
152 value = 'auto'; |
|
153 } |
|
154 } |
|
155 |
|
156 return value == 'auto' ? null : value; |
|
157 }, |
|
158 |
|
159 /** @id MochiKit.Style.setStyle */ |
|
160 setStyle: function (elem, style) { |
|
161 elem = MochiKit.DOM.getElement(elem); |
|
162 for (var name in style) { |
|
163 if (name == 'opacity') { |
|
164 MochiKit.Style.setOpacity(elem, style[name]); |
|
165 } else { |
|
166 elem.style[MochiKit.Base.camelize(name)] = style[name]; |
|
167 } |
|
168 } |
|
169 }, |
|
170 |
|
171 /** @id MochiKit.Style.setOpacity */ |
|
172 setOpacity: function (elem, o) { |
|
173 elem = MochiKit.DOM.getElement(elem); |
|
174 var self = MochiKit.Style; |
|
175 if (o == 1) { |
|
176 var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)); |
|
177 elem.style["opacity"] = toSet ? 0.999999 : 1.0; |
|
178 if (/MSIE/.test(navigator.userAgent)) { |
|
179 elem.style['filter'] = |
|
180 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, ''); |
|
181 } |
|
182 } else { |
|
183 if (o < 0.00001) { |
|
184 o = 0; |
|
185 } |
|
186 elem.style["opacity"] = o; |
|
187 if (/MSIE/.test(navigator.userAgent)) { |
|
188 elem.style['filter'] = |
|
189 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')'; |
|
190 } |
|
191 } |
|
192 }, |
|
193 |
|
194 /* |
|
195 |
|
196 getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0. |
|
197 Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved. |
|
198 License: BSD, http://developer.yahoo.net/yui/license.txt |
|
199 |
|
200 */ |
|
201 |
|
202 /** @id MochiKit.Style.getElementPosition */ |
|
203 getElementPosition: function (elem, /* optional */relativeTo) { |
|
204 var self = MochiKit.Style; |
|
205 var dom = MochiKit.DOM; |
|
206 elem = dom.getElement(elem); |
|
207 |
|
208 if (!elem || |
|
209 (!(elem.x && elem.y) && |
|
210 (!elem.parentNode === null || |
|
211 self.getStyle(elem, 'display') == 'none'))) { |
|
212 return undefined; |
|
213 } |
|
214 |
|
215 var c = new self.Coordinates(0, 0); |
|
216 var box = null; |
|
217 var parent = null; |
|
218 |
|
219 var d = MochiKit.DOM._document; |
|
220 var de = d.documentElement; |
|
221 var b = d.body; |
|
222 |
|
223 if (!elem.parentNode && elem.x && elem.y) { |
|
224 /* it's just a MochiKit.Style.Coordinates object */ |
|
225 c.x += elem.x || 0; |
|
226 c.y += elem.y || 0; |
|
227 } else if (elem.getBoundingClientRect) { // IE shortcut |
|
228 /* |
|
229 |
|
230 The IE shortcut can be off by two. We fix it. See: |
|
231 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp |
|
232 |
|
233 This is similar to the method used in |
|
234 MochiKit.Signal.Event.mouse(). |
|
235 |
|
236 */ |
|
237 box = elem.getBoundingClientRect(); |
|
238 |
|
239 c.x += box.left + |
|
240 (de.scrollLeft || b.scrollLeft) - |
|
241 (de.clientLeft || 0); |
|
242 |
|
243 c.y += box.top + |
|
244 (de.scrollTop || b.scrollTop) - |
|
245 (de.clientTop || 0); |
|
246 |
|
247 } else if (elem.offsetParent) { |
|
248 c.x += elem.offsetLeft; |
|
249 c.y += elem.offsetTop; |
|
250 parent = elem.offsetParent; |
|
251 |
|
252 if (parent != elem) { |
|
253 while (parent) { |
|
254 c.x += parent.offsetLeft; |
|
255 c.y += parent.offsetTop; |
|
256 parent = parent.offsetParent; |
|
257 } |
|
258 } |
|
259 |
|
260 /* |
|
261 |
|
262 Opera < 9 and old Safari (absolute) incorrectly account for |
|
263 body offsetTop and offsetLeft. |
|
264 |
|
265 */ |
|
266 var ua = navigator.userAgent.toLowerCase(); |
|
267 if ((typeof(opera) != 'undefined' && |
|
268 parseFloat(opera.version()) < 9) || |
|
269 (ua.indexOf('AppleWebKit') != -1 && |
|
270 self.getStyle(elem, 'position') == 'absolute')) { |
|
271 |
|
272 c.x -= b.offsetLeft; |
|
273 c.y -= b.offsetTop; |
|
274 |
|
275 } |
|
276 } |
|
277 |
|
278 if (typeof(relativeTo) != 'undefined') { |
|
279 relativeTo = arguments.callee(relativeTo); |
|
280 if (relativeTo) { |
|
281 c.x -= (relativeTo.x || 0); |
|
282 c.y -= (relativeTo.y || 0); |
|
283 } |
|
284 } |
|
285 |
|
286 if (elem.parentNode) { |
|
287 parent = elem.parentNode; |
|
288 } else { |
|
289 parent = null; |
|
290 } |
|
291 |
|
292 while (parent) { |
|
293 var tagName = parent.tagName.toUpperCase(); |
|
294 if (tagName === 'BODY' || tagName === 'HTML') { |
|
295 break; |
|
296 } |
|
297 var disp = self.getStyle(parent, 'display'); |
|
298 // Handle strange Opera bug for some display |
|
299 if (disp != 'inline' && disp != 'table-row') { |
|
300 c.x -= parent.scrollLeft; |
|
301 c.y -= parent.scrollTop; |
|
302 } |
|
303 if (parent.parentNode) { |
|
304 parent = parent.parentNode; |
|
305 } else { |
|
306 parent = null; |
|
307 } |
|
308 } |
|
309 |
|
310 return c; |
|
311 }, |
|
312 |
|
313 /** @id MochiKit.Style.setElementPosition */ |
|
314 setElementPosition: function (elem, newPos/* optional */, units) { |
|
315 elem = MochiKit.DOM.getElement(elem); |
|
316 if (typeof(units) == 'undefined') { |
|
317 units = 'px'; |
|
318 } |
|
319 var newStyle = {}; |
|
320 var isUndefNull = MochiKit.Base.isUndefinedOrNull; |
|
321 if (!isUndefNull(newPos.x)) { |
|
322 newStyle['left'] = newPos.x + units; |
|
323 } |
|
324 if (!isUndefNull(newPos.y)) { |
|
325 newStyle['top'] = newPos.y + units; |
|
326 } |
|
327 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); |
|
328 }, |
|
329 |
|
330 /** @id MochiKit.Style.getElementDimensions */ |
|
331 getElementDimensions: function (elem) { |
|
332 var self = MochiKit.Style; |
|
333 var dom = MochiKit.DOM; |
|
334 if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') { |
|
335 return new self.Dimensions(elem.w || 0, elem.h || 0); |
|
336 } |
|
337 elem = dom.getElement(elem); |
|
338 if (!elem) { |
|
339 return undefined; |
|
340 } |
|
341 var disp = self.getStyle(elem, 'display'); |
|
342 // display can be empty/undefined on WebKit/KHTML |
|
343 if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') { |
|
344 return new self.Dimensions(elem.offsetWidth || 0, |
|
345 elem.offsetHeight || 0); |
|
346 } |
|
347 var s = elem.style; |
|
348 var originalVisibility = s.visibility; |
|
349 var originalPosition = s.position; |
|
350 s.visibility = 'hidden'; |
|
351 s.position = 'absolute'; |
|
352 s.display = ''; |
|
353 var originalWidth = elem.offsetWidth; |
|
354 var originalHeight = elem.offsetHeight; |
|
355 s.display = 'none'; |
|
356 s.position = originalPosition; |
|
357 s.visibility = originalVisibility; |
|
358 return new self.Dimensions(originalWidth, originalHeight); |
|
359 }, |
|
360 |
|
361 /** @id MochiKit.Style.setElementDimensions */ |
|
362 setElementDimensions: function (elem, newSize/* optional */, units) { |
|
363 elem = MochiKit.DOM.getElement(elem); |
|
364 if (typeof(units) == 'undefined') { |
|
365 units = 'px'; |
|
366 } |
|
367 var newStyle = {}; |
|
368 var isUndefNull = MochiKit.Base.isUndefinedOrNull; |
|
369 if (!isUndefNull(newSize.w)) { |
|
370 newStyle['width'] = newSize.w + units; |
|
371 } |
|
372 if (!isUndefNull(newSize.h)) { |
|
373 newStyle['height'] = newSize.h + units; |
|
374 } |
|
375 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); |
|
376 }, |
|
377 |
|
378 /** @id MochiKit.Style.setDisplayForElement */ |
|
379 setDisplayForElement: function (display, element/*, ...*/) { |
|
380 var elements = MochiKit.Base.extend(null, arguments, 1); |
|
381 var getElement = MochiKit.DOM.getElement; |
|
382 for (var i = 0; i < elements.length; i++) { |
|
383 element = getElement(elements[i]); |
|
384 if (element) { |
|
385 element.style.display = display; |
|
386 } |
|
387 } |
|
388 }, |
|
389 |
|
390 /** @id MochiKit.Style.getViewportDimensions */ |
|
391 getViewportDimensions: function () { |
|
392 var d = new MochiKit.Style.Dimensions(); |
|
393 |
|
394 var w = MochiKit.DOM._window; |
|
395 var b = MochiKit.DOM._document.body; |
|
396 |
|
397 if (w.innerWidth) { |
|
398 d.w = w.innerWidth; |
|
399 d.h = w.innerHeight; |
|
400 } else if (b.parentElement.clientWidth) { |
|
401 d.w = b.parentElement.clientWidth; |
|
402 d.h = b.parentElement.clientHeight; |
|
403 } else if (b && b.clientWidth) { |
|
404 d.w = b.clientWidth; |
|
405 d.h = b.clientHeight; |
|
406 } |
|
407 return d; |
|
408 }, |
|
409 |
|
410 /** @id MochiKit.Style.getViewportPosition */ |
|
411 getViewportPosition: function () { |
|
412 var c = new MochiKit.Style.Coordinates(0, 0); |
|
413 var d = MochiKit.DOM._document; |
|
414 var de = d.documentElement; |
|
415 var db = d.body; |
|
416 if (de && (de.scrollTop || de.scrollLeft)) { |
|
417 c.x = de.scrollLeft; |
|
418 c.y = de.scrollTop; |
|
419 } else if (db) { |
|
420 c.x = db.scrollLeft; |
|
421 c.y = db.scrollTop; |
|
422 } |
|
423 return c; |
|
424 }, |
|
425 |
|
426 __new__: function () { |
|
427 var m = MochiKit.Base; |
|
428 |
|
429 this.elementPosition = this.getElementPosition; |
|
430 this.elementDimensions = this.getElementDimensions; |
|
431 |
|
432 this.hideElement = m.partial(this.setDisplayForElement, 'none'); |
|
433 this.showElement = m.partial(this.setDisplayForElement, 'block'); |
|
434 |
|
435 this.EXPORT_TAGS = { |
|
436 ':common': this.EXPORT, |
|
437 ':all': m.concat(this.EXPORT, this.EXPORT_OK) |
|
438 }; |
|
439 |
|
440 m.nameFunctions(this); |
|
441 } |
|
442 }); |
|
443 |
|
444 MochiKit.Style.__new__(); |
|
445 MochiKit.Base._exportSymbols(this, MochiKit.Style); |