Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /***
3 MochiKit.Style 1.4.2
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
9 ***/
11 MochiKit.Base._deps('Style', ['Base', 'DOM']);
13 MochiKit.Style.NAME = 'MochiKit.Style';
14 MochiKit.Style.VERSION = '1.4.2';
15 MochiKit.Style.__repr__ = function () {
16 return '[' + this.NAME + ' ' + this.VERSION + ']';
17 };
18 MochiKit.Style.toString = function () {
19 return this.__repr__();
20 };
22 MochiKit.Style.EXPORT_OK = [];
24 MochiKit.Style.EXPORT = [
25 'setStyle',
26 'setOpacity',
27 'getStyle',
28 'getElementDimensions',
29 'elementDimensions', // deprecated
30 'setElementDimensions',
31 'getElementPosition',
32 'elementPosition', // deprecated
33 'setElementPosition',
34 "makePositioned",
35 "undoPositioned",
36 "makeClipping",
37 "undoClipping",
38 'setDisplayForElement',
39 'hideElement',
40 'showElement',
41 'getViewportDimensions',
42 'getViewportPosition',
43 'Dimensions',
44 'Coordinates'
45 ];
48 /*
50 Dimensions
52 */
53 /** @id MochiKit.Style.Dimensions */
54 MochiKit.Style.Dimensions = function (w, h) {
55 this.w = w;
56 this.h = h;
57 };
59 MochiKit.Style.Dimensions.prototype.__repr__ = function () {
60 var repr = MochiKit.Base.repr;
61 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
62 };
64 MochiKit.Style.Dimensions.prototype.toString = function () {
65 return this.__repr__();
66 };
69 /*
71 Coordinates
73 */
74 /** @id MochiKit.Style.Coordinates */
75 MochiKit.Style.Coordinates = function (x, y) {
76 this.x = x;
77 this.y = y;
78 };
80 MochiKit.Style.Coordinates.prototype.__repr__ = function () {
81 var repr = MochiKit.Base.repr;
82 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
83 };
85 MochiKit.Style.Coordinates.prototype.toString = function () {
86 return this.__repr__();
87 };
90 MochiKit.Base.update(MochiKit.Style, {
92 /** @id MochiKit.Style.getStyle */
93 getStyle: function (elem, cssProperty) {
94 var dom = MochiKit.DOM;
95 var d = dom._document;
97 elem = dom.getElement(elem);
98 cssProperty = MochiKit.Base.camelize(cssProperty);
100 if (!elem || elem == d) {
101 return undefined;
102 }
103 if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') {
104 var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
105 if (opacity && opacity[1]) {
106 return parseFloat(opacity[1]) / 100;
107 }
108 return 1.0;
109 }
110 if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') {
111 if (elem.style["float"]) {
112 return elem.style["float"];
113 } else if (elem.style.cssFloat) {
114 return elem.style.cssFloat;
115 } else if (elem.style.styleFloat) {
116 return elem.style.styleFloat;
117 } else {
118 return "none";
119 }
120 }
121 var value = elem.style ? elem.style[cssProperty] : null;
122 if (!value) {
123 if (d.defaultView && d.defaultView.getComputedStyle) {
124 var css = d.defaultView.getComputedStyle(elem, null);
125 cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
126 ).toLowerCase(); // from dojo.style.toSelectorCase
127 value = css ? css.getPropertyValue(cssProperty) : null;
128 } else if (elem.currentStyle) {
129 value = elem.currentStyle[cssProperty];
130 if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') {
131 /* Convert to px using an hack from Dean Edwards */
132 var left = elem.style.left;
133 var rsLeft = elem.runtimeStyle.left;
134 elem.runtimeStyle.left = elem.currentStyle.left;
135 elem.style.left = value || 0;
136 value = elem.style.pixelLeft + "px";
137 elem.style.left = left;
138 elem.runtimeStyle.left = rsLeft;
139 }
140 }
141 }
142 if (cssProperty == 'opacity') {
143 value = parseFloat(value);
144 }
146 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
147 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
148 value = 'auto';
149 }
150 }
152 return value == 'auto' ? null : value;
153 },
155 /** @id MochiKit.Style.setStyle */
156 setStyle: function (elem, style) {
157 elem = MochiKit.DOM.getElement(elem);
158 for (var name in style) {
159 switch (name) {
160 case 'opacity':
161 MochiKit.Style.setOpacity(elem, style[name]);
162 break;
163 case 'float':
164 case 'cssFloat':
165 case 'styleFloat':
166 if (typeof(elem.style["float"]) != "undefined") {
167 elem.style["float"] = style[name];
168 } else if (typeof(elem.style.cssFloat) != "undefined") {
169 elem.style.cssFloat = style[name];
170 } else {
171 elem.style.styleFloat = style[name];
172 }
173 break;
174 default:
175 elem.style[MochiKit.Base.camelize(name)] = style[name];
176 }
177 }
178 },
180 /** @id MochiKit.Style.setOpacity */
181 setOpacity: function (elem, o) {
182 elem = MochiKit.DOM.getElement(elem);
183 var self = MochiKit.Style;
184 if (o == 1) {
185 var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
186 elem.style["opacity"] = toSet ? 0.999999 : 1.0;
187 if (/MSIE/.test(navigator.userAgent)) {
188 elem.style['filter'] =
189 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
190 }
191 } else {
192 if (o < 0.00001) {
193 o = 0;
194 }
195 elem.style["opacity"] = o;
196 if (/MSIE/.test(navigator.userAgent)) {
197 elem.style['filter'] =
198 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
199 }
200 }
201 },
203 /*
205 getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
206 Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
207 License: BSD, http://developer.yahoo.net/yui/license.txt
209 */
211 /** @id MochiKit.Style.getElementPosition */
212 getElementPosition: function (elem, /* optional */relativeTo) {
213 var self = MochiKit.Style;
214 var dom = MochiKit.DOM;
215 elem = dom.getElement(elem);
217 if (!elem ||
218 (!(elem.x && elem.y) &&
219 (!elem.parentNode === null ||
220 self.getStyle(elem, 'display') == 'none'))) {
221 return undefined;
222 }
224 var c = new self.Coordinates(0, 0);
225 var box = null;
226 var parent = null;
228 var d = MochiKit.DOM._document;
229 var de = d.documentElement;
230 var b = d.body;
232 if (!elem.parentNode && elem.x && elem.y) {
233 /* it's just a MochiKit.Style.Coordinates object */
234 c.x += elem.x || 0;
235 c.y += elem.y || 0;
236 } else if (elem.getBoundingClientRect) { // IE shortcut
237 /*
239 The IE shortcut can be off by two. We fix it. See:
240 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
242 This is similar to the method used in
243 MochiKit.Signal.Event.mouse().
245 */
246 box = elem.getBoundingClientRect();
248 c.x += box.left +
249 (de.scrollLeft || b.scrollLeft) -
250 (de.clientLeft || 0);
252 c.y += box.top +
253 (de.scrollTop || b.scrollTop) -
254 (de.clientTop || 0);
256 } else if (elem.offsetParent) {
257 c.x += elem.offsetLeft;
258 c.y += elem.offsetTop;
259 parent = elem.offsetParent;
261 if (parent != elem) {
262 while (parent) {
263 c.x += parseInt(parent.style.borderLeftWidth) || 0;
264 c.y += parseInt(parent.style.borderTopWidth) || 0;
265 c.x += parent.offsetLeft;
266 c.y += parent.offsetTop;
267 parent = parent.offsetParent;
268 }
269 }
271 /*
273 Opera < 9 and old Safari (absolute) incorrectly account for
274 body offsetTop and offsetLeft.
276 */
277 var ua = navigator.userAgent.toLowerCase();
278 if ((typeof(opera) != 'undefined' &&
279 parseFloat(opera.version()) < 9) ||
280 (ua.indexOf('AppleWebKit') != -1 &&
281 self.getStyle(elem, 'position') == 'absolute')) {
283 c.x -= b.offsetLeft;
284 c.y -= b.offsetTop;
286 }
288 // Adjust position for strange Opera scroll bug
289 if (elem.parentNode) {
290 parent = elem.parentNode;
291 } else {
292 parent = null;
293 }
294 while (parent) {
295 var tagName = parent.tagName.toUpperCase();
296 if (tagName === 'BODY' || tagName === 'HTML') {
297 break;
298 }
299 var disp = self.getStyle(parent, 'display');
300 // Handle strange Opera bug for some display
301 if (disp.search(/^inline|table-row.*$/i)) {
302 c.x -= parent.scrollLeft;
303 c.y -= parent.scrollTop;
304 }
305 if (parent.parentNode) {
306 parent = parent.parentNode;
307 } else {
308 parent = null;
309 }
310 }
311 }
313 if (typeof(relativeTo) != 'undefined') {
314 relativeTo = arguments.callee(relativeTo);
315 if (relativeTo) {
316 c.x -= (relativeTo.x || 0);
317 c.y -= (relativeTo.y || 0);
318 }
319 }
321 return c;
322 },
324 /** @id MochiKit.Style.setElementPosition */
325 setElementPosition: function (elem, newPos/* optional */, units) {
326 elem = MochiKit.DOM.getElement(elem);
327 if (typeof(units) == 'undefined') {
328 units = 'px';
329 }
330 var newStyle = {};
331 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
332 if (!isUndefNull(newPos.x)) {
333 newStyle['left'] = newPos.x + units;
334 }
335 if (!isUndefNull(newPos.y)) {
336 newStyle['top'] = newPos.y + units;
337 }
338 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
339 },
341 /** @id MochiKit.Style.makePositioned */
342 makePositioned: function (element) {
343 element = MochiKit.DOM.getElement(element);
344 var pos = MochiKit.Style.getStyle(element, 'position');
345 if (pos == 'static' || !pos) {
346 element.style.position = 'relative';
347 // Opera returns the offset relative to the positioning context,
348 // when an element is position relative but top and left have
349 // not been defined
350 if (/Opera/.test(navigator.userAgent)) {
351 element.style.top = 0;
352 element.style.left = 0;
353 }
354 }
355 },
357 /** @id MochiKit.Style.undoPositioned */
358 undoPositioned: function (element) {
359 element = MochiKit.DOM.getElement(element);
360 if (element.style.position == 'relative') {
361 element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
362 }
363 },
365 /** @id MochiKit.Style.makeClipping */
366 makeClipping: function (element) {
367 element = MochiKit.DOM.getElement(element);
368 var s = element.style;
369 var oldOverflow = { 'overflow': s.overflow,
370 'overflow-x': s.overflowX,
371 'overflow-y': s.overflowY };
372 if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
373 element.style.overflow = 'hidden';
374 element.style.overflowX = 'hidden';
375 element.style.overflowY = 'hidden';
376 }
377 return oldOverflow;
378 },
380 /** @id MochiKit.Style.undoClipping */
381 undoClipping: function (element, overflow) {
382 element = MochiKit.DOM.getElement(element);
383 if (typeof(overflow) == 'string') {
384 element.style.overflow = overflow;
385 } else if (overflow != null) {
386 element.style.overflow = overflow['overflow'];
387 element.style.overflowX = overflow['overflow-x'];
388 element.style.overflowY = overflow['overflow-y'];
389 }
390 },
392 /** @id MochiKit.Style.getElementDimensions */
393 getElementDimensions: function (elem, contentSize/*optional*/) {
394 var self = MochiKit.Style;
395 var dom = MochiKit.DOM;
396 if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
397 return new self.Dimensions(elem.w || 0, elem.h || 0);
398 }
399 elem = dom.getElement(elem);
400 if (!elem) {
401 return undefined;
402 }
403 var disp = self.getStyle(elem, 'display');
404 // display can be empty/undefined on WebKit/KHTML
405 if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') {
406 var s = elem.style;
407 var originalVisibility = s.visibility;
408 var originalPosition = s.position;
409 var originalDisplay = s.display;
410 s.visibility = 'hidden';
411 s.position = 'absolute';
412 s.display = self._getDefaultDisplay(elem);
413 var originalWidth = elem.offsetWidth;
414 var originalHeight = elem.offsetHeight;
415 s.display = originalDisplay;
416 s.position = originalPosition;
417 s.visibility = originalVisibility;
418 } else {
419 originalWidth = elem.offsetWidth || 0;
420 originalHeight = elem.offsetHeight || 0;
421 }
422 if (contentSize) {
423 var tableCell = 'colSpan' in elem && 'rowSpan' in elem;
424 var collapse = (tableCell && elem.parentNode && self.getStyle(
425 elem.parentNode, 'borderCollapse') == 'collapse')
426 if (collapse) {
427 if (/MSIE/.test(navigator.userAgent)) {
428 var borderLeftQuota = elem.previousSibling? 0.5 : 1;
429 var borderRightQuota = elem.nextSibling? 0.5 : 1;
430 }
431 else {
432 var borderLeftQuota = 0.5;
433 var borderRightQuota = 0.5;
434 }
435 } else {
436 var borderLeftQuota = 1;
437 var borderRightQuota = 1;
438 }
439 originalWidth -= Math.round(
440 (parseFloat(self.getStyle(elem, 'paddingLeft')) || 0)
441 + (parseFloat(self.getStyle(elem, 'paddingRight')) || 0)
442 + borderLeftQuota *
443 (parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0)
444 + borderRightQuota *
445 (parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0)
446 );
447 if (tableCell) {
448 if (/Opera/.test(navigator.userAgent)
449 && !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) {
450 var borderHeightQuota = 0;
451 } else if (/MSIE/.test(navigator.userAgent)) {
452 var borderHeightQuota = 1;
453 } else {
454 var borderHeightQuota = collapse? 0.5 : 1;
455 }
456 } else {
457 var borderHeightQuota = 1;
458 }
459 originalHeight -= Math.round(
460 (parseFloat(self.getStyle(elem, 'paddingTop')) || 0)
461 + (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0)
462 + borderHeightQuota * (
463 (parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0)
464 + (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0))
465 );
466 }
467 return new self.Dimensions(originalWidth, originalHeight);
468 },
470 /** @id MochiKit.Style.setElementDimensions */
471 setElementDimensions: function (elem, newSize/* optional */, units) {
472 elem = MochiKit.DOM.getElement(elem);
473 if (typeof(units) == 'undefined') {
474 units = 'px';
475 }
476 var newStyle = {};
477 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
478 if (!isUndefNull(newSize.w)) {
479 newStyle['width'] = newSize.w + units;
480 }
481 if (!isUndefNull(newSize.h)) {
482 newStyle['height'] = newSize.h + units;
483 }
484 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
485 },
487 _getDefaultDisplay: function (elem) {
488 var self = MochiKit.Style;
489 var dom = MochiKit.DOM;
490 elem = dom.getElement(elem);
491 if (!elem) {
492 return undefined;
493 }
494 var tagName = elem.tagName.toUpperCase();
495 return self._defaultDisplay[tagName] || 'block';
496 },
498 /** @id MochiKit.Style.setDisplayForElement */
499 setDisplayForElement: function (display, element/*, ...*/) {
500 var elements = MochiKit.Base.extend(null, arguments, 1);
501 var getElement = MochiKit.DOM.getElement;
502 for (var i = 0; i < elements.length; i++) {
503 element = getElement(elements[i]);
504 if (element) {
505 element.style.display = display;
506 }
507 }
508 },
510 /** @id MochiKit.Style.getViewportDimensions */
511 getViewportDimensions: function () {
512 var d = new MochiKit.Style.Dimensions();
513 var w = MochiKit.DOM._window;
514 var b = MochiKit.DOM._document.body;
515 if (w.innerWidth) {
516 d.w = w.innerWidth;
517 d.h = w.innerHeight;
518 } else if (b && b.parentElement && b.parentElement.clientWidth) {
519 d.w = b.parentElement.clientWidth;
520 d.h = b.parentElement.clientHeight;
521 } else if (b && b.clientWidth) {
522 d.w = b.clientWidth;
523 d.h = b.clientHeight;
524 }
525 return d;
526 },
528 /** @id MochiKit.Style.getViewportPosition */
529 getViewportPosition: function () {
530 var c = new MochiKit.Style.Coordinates(0, 0);
531 var d = MochiKit.DOM._document;
532 var de = d.documentElement;
533 var db = d.body;
534 if (de && (de.scrollTop || de.scrollLeft)) {
535 c.x = de.scrollLeft;
536 c.y = de.scrollTop;
537 } else if (db) {
538 c.x = db.scrollLeft;
539 c.y = db.scrollTop;
540 }
541 return c;
542 },
544 __new__: function () {
545 var m = MochiKit.Base;
547 var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR',
548 'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL',
549 'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB',
550 'SUP','TEXTAREA','TT','U','VAR'];
551 this._defaultDisplay = { 'TABLE': 'table',
552 'THEAD': 'table-header-group',
553 'TBODY': 'table-row-group',
554 'TFOOT': 'table-footer-group',
555 'COLGROUP': 'table-column-group',
556 'COL': 'table-column',
557 'TR': 'table-row',
558 'TD': 'table-cell',
559 'TH': 'table-cell',
560 'CAPTION': 'table-caption',
561 'LI': 'list-item',
562 'INPUT': 'inline-block',
563 'SELECT': 'inline-block' };
564 // CSS 'display' support in IE6/7 is just broken...
565 if (/MSIE/.test(navigator.userAgent)) {
566 for (var k in this._defaultDisplay) {
567 var v = this._defaultDisplay[k];
568 if (v.indexOf('table') == 0) {
569 this._defaultDisplay[k] = 'block';
570 }
571 }
572 }
573 for (var i = 0; i < inlines.length; i++) {
574 this._defaultDisplay[inlines[i]] = 'inline';
575 }
577 this.elementPosition = this.getElementPosition;
578 this.elementDimensions = this.getElementDimensions;
580 this.hideElement = m.partial(this.setDisplayForElement, 'none');
581 // TODO: showElement could be improved by using getDefaultDisplay.
582 this.showElement = m.partial(this.setDisplayForElement, 'block');
584 this.EXPORT_TAGS = {
585 ':common': this.EXPORT,
586 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
587 };
589 m.nameFunctions(this);
590 }
591 });
593 MochiKit.Style.__new__();
594 MochiKit.Base._exportSymbols(this, MochiKit.Style);