/***

MochiKit.Style 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005-2006 Bob Ippolito, Beau Hartshorne.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.Style');
    dojo.require('MochiKit.Base');
    dojo.require('MochiKit.DOM');
}
if (typeof(JSAN) != 'undefined') {
    JSAN.use('MochiKit.Base', []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined') {
        throw '';
    }
} catch (e) {
    throw 'MochiKit.Style depends on MochiKit.Base!';
}

try {
    if (typeof(MochiKit.DOM) == 'undefined') {
        throw '';
    }
} catch (e) {
    throw 'MochiKit.Style depends on MochiKit.DOM!';
}


if (typeof(MochiKit.Style) == 'undefined') {
    MochiKit.Style = {};
}

MochiKit.Style.NAME = 'MochiKit.Style';
MochiKit.Style.VERSION = '1.4';
MochiKit.Style.__repr__ = function () {
    return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.Style.toString = function () {
    return this.__repr__();
};

MochiKit.Style.EXPORT_OK = [];

MochiKit.Style.EXPORT = [
    'setOpacity',
    'getOpacity',
    'setStyle',
    'getStyle', // temporary
    'computedStyle',
    'getElementDimensions',
    'elementDimensions', // deprecated
    'setElementDimensions',
    'getElementPosition',
    'elementPosition', // deprecated
    'setElementPosition',
    'setDisplayForElement',
    'hideElement',
    'showElement',
    'getViewportDimensions',
    'getViewportPosition',
    'Dimensions',
    'Coordinates'
];


/*

    Dimensions
    
*/
/** @id MochiKit.Style.Dimensions */
MochiKit.Style.Dimensions = function (w, h) {
    this.w = w;
    this.h = h;
};

MochiKit.Style.Dimensions.prototype.__repr__ = function () {
    var repr = MochiKit.Base.repr;
    return '{w: '  + repr(this.w) + ', h: ' + repr(this.h) + '}';
};

MochiKit.Style.Dimensions.prototype.toString = function () {
    return this.__repr__();
};


/*

    Coordinates

*/
/** @id MochiKit.Style.Coordinates */
MochiKit.Style.Coordinates = function (x, y) {
    this.x = x;
    this.y = y;
};

MochiKit.Style.Coordinates.prototype.__repr__ = function () {
    var repr = MochiKit.Base.repr;
    return '{x: '  + repr(this.x) + ', y: ' + repr(this.y) + '}';
};

MochiKit.Style.Coordinates.prototype.toString = function () {
    return this.__repr__();
};


MochiKit.Base.update(MochiKit.Style, {

    /** @id MochiKit.Style.computedStyle */
    computedStyle: function (elem, cssProperty) {
        var dom = MochiKit.DOM;
        var d = dom._document;
        
        elem = dom.getElement(elem);
        cssProperty = MochiKit.Base.camelize(cssProperty);
        
        if (!elem || elem == d) {
            return undefined;
        }

        /* from YUI 0.10.0 */
        if (cssProperty == 'opacity' && elem.filters) { // IE opacity
            try {
                return elem.filters.item('DXImageTransform.Microsoft.Alpha'
                    ).opacity / 100;
            } catch(e) {
                try {
                    return elem.filters.item('alpha').opacity / 100;
                } catch(e) {}
            }
        }
        
        if (elem.currentStyle) {
            return elem.currentStyle[cssProperty];
        }
        if (typeof(d.defaultView) == 'undefined') {
            return undefined;
        }
        if (d.defaultView === null) {
            return undefined;
        }
        var style = d.defaultView.getComputedStyle(elem, null);
        if (typeof(style) == 'undefined' || style === null) {
            return undefined;
        }
        
        var selectorCase = cssProperty.replace(/([A-Z])/g, '-$1'
            ).toLowerCase(); // from dojo.style.toSelectorCase
            
        return style.getPropertyValue(selectorCase);
    },
    
    /** @id MochiKit.Style.getStyle */
    getStyle: function (elem, style) {
        elem = MochiKit.DOM.getElement(elem);
        var value = elem.style[MochiKit.Base.camelize(style)];
        if (!value) {
            if (document.defaultView && document.defaultView.getComputedStyle) {
                var css = document.defaultView.getComputedStyle(elem, null);
                value = css ? css.getPropertyValue(style) : null;
            } else if (elem.currentStyle) {
                value = elem.currentStyle[MochiKit.Base.camelize(style)];
            }
        }

        if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], style) != -1)) {
            if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
                value = 'auto';
            }
        }

        return value == 'auto' ? null : value;
    },

    /** @id MochiKit.Style.setStyle */
    setStyle: function (elem, style) {
        elem = MochiKit.DOM.getElement(elem);
        for (name in style) {
            elem.style[MochiKit.Base.camelize(name)] = style[name];
        }
    },

    /** @id MochiKit.Style.getOpacity */
    getOpacity: function (elem) {
        var opacity;
        if (opacity = MochiKit.Style.getStyle(elem, 'opacity')) {
            return parseFloat(opacity);
        }
        if (opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) {
            if (opacity[1]) {
                return parseFloat(opacity[1]) / 100;
            }
        }
        return 1.0;
    },
    /** @id MochiKit.Style.setOpacity */
    setOpacity: function(elem, o) {
        elem = MochiKit.DOM.getElement(elem);
        var self = MochiKit.Style;
        if (o == 1) {
            var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|Safari|KHTML/.test(navigator.userAgent));
            self.setStyle(elem, {opacity: toSet ? 0.999999 : 1.0});
            if (/MSIE/.test(navigator.userAgent)) {
                self.setStyle(elem, {filter:
                    self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '')});
            }
        } else {
            if (o < 0.00001) {
                o = 0;
            }
            self.setStyle(elem, {opacity: o});
            if (/MSIE/.test(navigator.userAgent)) {
                self.setStyle(elem,
                    {filter: self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')' });
            }
        }
    },

    /* 

        getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
        Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
        License: BSD, http://developer.yahoo.net/yui/license.txt

    */
    
    /** @id MochiKit.Style.getElementPosition */    
    getElementPosition: function (elem, /* optional */relativeTo) {
        var self = MochiKit.Style;
        var dom = MochiKit.DOM;        
        elem = dom.getElement(elem);
        
        if (!elem || 
            (!(elem.x && elem.y) && 
            (!elem.parentNode == null || 
            self.computedStyle(elem, 'display') == 'none'))) {
            return undefined;
        }

        var c = new self.Coordinates(0, 0);        
        var box = null;
        var parent = null;
        
        var d = MochiKit.DOM._document;
        var de = d.documentElement;
        var b = d.body;            
    
        if (!elem.parentNode && elem.x && elem.y) {
            /* it's just a MochiKit.Style.Coordinates object */
            c.x += elem.x || 0;
            c.y += elem.y || 0;
        } else if (elem.getBoundingClientRect) { // IE shortcut
            /*
            
                The IE shortcut can be off by two. We fix it. See:
                http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
                
                This is similar to the method used in 
                MochiKit.Signal.Event.mouse().
                
            */
            box = elem.getBoundingClientRect();
                        
            c.x += box.left + 
                (de.scrollLeft || b.scrollLeft) - 
                (de.clientLeft || 0);
            
            c.y += box.top + 
                (de.scrollTop || b.scrollTop) - 
                (de.clientTop || 0);
            
        } else if (elem.offsetParent) {
            c.x += elem.offsetLeft;
            c.y += elem.offsetTop;
            parent = elem.offsetParent;
            
            if (parent != elem) {
                while (parent) {
                    c.x += parent.offsetLeft;
                    c.y += parent.offsetTop;
                    parent = parent.offsetParent;
                }
            }

            /*
                
                Opera < 9 and old Safari (absolute) incorrectly account for 
                body offsetTop and offsetLeft.
                
            */
            var ua = navigator.userAgent.toLowerCase();
            if ((typeof(opera) != 'undefined' && 
                parseFloat(opera.version()) < 9) || 
                (ua.indexOf('safari') != -1 && 
                self.computedStyle(elem, 'position') == 'absolute')) {
                                
                c.x -= b.offsetLeft;
                c.y -= b.offsetTop;
                
            }
        }
        
        if (typeof(relativeTo) != 'undefined') {
            relativeTo = arguments.callee(relativeTo);
            if (relativeTo) {
                c.x -= (relativeTo.x || 0);
                c.y -= (relativeTo.y || 0);
            }
        }
        
        if (elem.parentNode) {
            parent = elem.parentNode;
        } else {
            parent = null;
        }
        
        while (parent) {
            var tagName = parent.tagName.toUpperCase();
            if (tagName === 'BODY' || tagName === 'HTML') {
                break;
            }
            c.x -= parent.scrollLeft;
            c.y -= parent.scrollTop;        
            if (parent.parentNode) {
                parent = parent.parentNode;
            } else {
                parent = null;
            }
        }
        
        return c;
    },
        
    /** @id MochiKit.Style.setElementPosition */    
    setElementPosition: function (elem, newPos/* optional */, units) {
        elem = MochiKit.DOM.getElement(elem);
        if (typeof(units) == 'undefined') {
            units = 'px';
        }
        var newStyle = {};
        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
        if (!isUndefNull(newPos.x)) {
            newStyle['left'] = newPos.x + units;
        }
        if (!isUndefNull(newPos.y)) {
            newStyle['top'] = newPos.y + units;
        }
        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
    },

    /** @id MochiKit.Style.getElementDimensions */
    getElementDimensions: function (elem) {
        var self = MochiKit.Style;
        var dom = MochiKit.DOM;
        if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
            return new self.Dimensions(elem.w || 0, elem.h || 0);
        }
        elem = dom.getElement(elem);
        if (!elem) {
            return undefined;
        }
        var disp = self.computedStyle(elem, 'display'); 
        // display can be empty/undefined on WebKit/KHTML
        if (disp != 'none' && disp != '' && typeof(disp) != 'undefined') { 
            return new self.Dimensions(elem.offsetWidth || 0, 
                elem.offsetHeight || 0);
        }
        var s = elem.style;
        var originalVisibility = s.visibility;
        var originalPosition = s.position;
        s.visibility = 'hidden';
        s.position = 'absolute';
        s.display = '';
        var originalWidth = elem.offsetWidth;
        var originalHeight = elem.offsetHeight;
        s.display = 'none';
        s.position = originalPosition; 
        s.visibility = originalVisibility;
        return new self.Dimensions(originalWidth, originalHeight);
    },

    /** @id MochiKit.Style.setElementDimensions */    
    setElementDimensions: function (elem, newSize/* optional */, units) {
        elem = MochiKit.DOM.getElement(elem);
        if (typeof(units) == 'undefined') {
            units = 'px';
        }
        var newStyle = {};
        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
        if (!isUndefNull(newSize.w)) {
            newStyle['width'] = newSize.w + units;
        }
        if (!isUndefNull(newSize.h)) {
            newStyle['height'] = newSize.h + units;
        }
        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
    },

    /** @id MochiKit.Style.setDisplayForElement */
    setDisplayForElement: function (display, element/*, ...*/) {
        var elements = MochiKit.Base.extend(null, arguments, 1);
        var getElement = MochiKit.DOM.getElement;
        for (var i = 0; i < elements.length; i++) {
            var element = getElement(elements[i]);
            if (element) {
                element.style.display = display;
            }
        }
    },

    /** @id MochiKit.Style.getViewportDimensions */
    getViewportDimensions: function () {
        var d = new MochiKit.Style.Dimensions();
        
        var w = MochiKit.DOM._window;
        var b = MochiKit.DOM._document.body;
        
        if (w.innerWidth) {
            d.w = w.innerWidth;
            d.h = w.innerHeight;
        } else if (b.parentElement.clientWidth) {
            d.w = b.parentElement.clientWidth;
            d.h = b.parentElement.clientHeight;
        } else if (b && b.clientWidth) {
            d.w = b.clientWidth;
            d.h = b.clientHeight;
        }
        return d;
    },

    /** @id MochiKit.Style.getViewportPosition */
    getViewportPosition: function () {
        var c = new MochiKit.Style.Coordinates(0, 0);
        var d = MochiKit.DOM._document;
        var de = d.documentElement;
        var db = d.body;
        if (de && (de.scrollTop || de.scrollLeft)) {
            c.x = de.scrollLeft;
            c.y = de.scrollTop;
        } else if (db) {
            c.x = db.scrollLeft;
            c.y = db.scrollTop;
        }
        return c;
    },

    __new__: function () {
        var m = MochiKit.Base;
        
        this.elementPosition = this.getElementPosition;
        this.elementDimensions = this.getElementDimensions;
        
        this.hideElement = m.partial(this.setDisplayForElement, 'none');
        this.showElement = m.partial(this.setDisplayForElement, 'block');
        
        this.EXPORT_TAGS = {
            ':common': this.EXPORT,
            ':all': m.concat(this.EXPORT, this.EXPORT_OK)
        };

        m.nameFunctions(this);
    }
});

MochiKit.Style.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Style);
