diff --git a/AppKit/CPCompatibility.j b/AppKit/CPCompatibility.j index 8dd1686d5f..8a0e3c0234 100644 --- a/AppKit/CPCompatibility.j +++ b/AppKit/CPCompatibility.j @@ -83,7 +83,8 @@ CPCanvasParentDrawErrorsOnMovementBug = 1 << 0; var USER_AGENT = "", PLATFORM_ENGINE = CPUnknownBrowserEngine, PLATFORM_FEATURES = 0, - PLATFORM_BUGS = 0; + PLATFORM_BUGS = 0, + PLATFORM_STYLE_JS_PROPERTIES = {}; // default these features to true @@ -273,3 +274,87 @@ else CPUndoKeyEquivalentModifierMask = CPControlKeyMask; CPRedoKeyEquivalentModifierMask = CPControlKeyMask; } + +/*! + Return the properly prefixed JS property for the given name. E.g. in a webkit browser, + CPBrowserStyleProperty('transition') -> WebkitTransition + + While technically not a style property, style related event handler names are also supported. + CPBrowserStyleProperty('transitionend') -> 'webkitTransitionEnd' + + CSS is only available in platform(dom), so don't rely too heavily on it. +*/ +function CPBrowserStyleProperty(aProperty) +{ + var lowerProperty = aProperty.toLowerCase(); + + if (PLATFORM_STYLE_JS_PROPERTIES[lowerProperty] === undefined) + { + var r = nil; + +#if PLATFORM(DOM) + var testElement = document.createElement('div'); + + switch (lowerProperty) + { + case 'transitionend': + var candidates = { + 'WebkitTransition' : 'webkitTransitionEnd', + 'MozTransition' : 'transitionend', + 'OTransition' : 'oTransitionEnd', + 'msTransition' : 'MSTransitionEnd', + 'transition' : 'transitionend' + }; + + r = candidates[PLATFORM_STYLE_JS_PROPERTIES['transition']] || nil; + break; + default: + var prefixes = ["Webkit", "Moz", "O", "ms"], + capProperty = [aProperty capitalizedString]; + + for (var i = 0; i < prefixes.length; i++) + { + if (prefixes[i] + capProperty in testElement.style) + { + r = prefixes[i] + capProperty; + break; + } + } + + if (!r && lowerProperty in testElement.style) + r = lowerProperty; + + break; + } +#endif + + PLATFORM_STYLE_JS_PROPERTIES[lowerProperty] = r; + } + + return PLATFORM_STYLE_JS_PROPERTIES[lowerProperty]; +} + +function CPBrowserCSSProperty(aProperty) +{ + var browserProperty = CPBrowserStyleProperty(aProperty); + + if (!browserProperty) + return nil; + + var prefixes = { + 'Webkit': '-webkit-', + 'Moz': '-moz-', + 'O': '-o-', + 'ms': '-ms-' + }; + + for (var prefix in prefixes) + { + if (browserProperty.substring(0, prefix.length) == prefix) + { + return prefixes[prefix] + browserProperty.substring(prefix.length).toLowerCase(); + } + } + + return browserProperty.toLowerCase(); +} diff --git a/AppKit/_CPAttachedWindow.j b/AppKit/_CPAttachedWindow.j index 2ac249dfa6..52c0d81f49 100644 --- a/AppKit/_CPAttachedWindow.j +++ b/AppKit/_CPAttachedWindow.j @@ -134,7 +134,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, [self setMovableByWindowBackground:YES]; [self setHasShadow:NO]; - [self setCSS3Property:@"TransitionProperty" value:@"-webkit-transform, opacity"]; + [self setCSS3Property:@"TransitionProperty" value:CPBrowserCSSProperty('transform') + @", opacity"]; [_windowView setNeedsDisplay:YES]; } @@ -350,25 +350,18 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, } /*! @ignore */ -- (void)setCSS3Property:(CPString)property value:(CPString)value +- (void)setCSS3Property:(CPString)aProperty value:(CPString)value { - _DOMElement.style['webkit' + property] = value; + var browserProperty = CPBrowserStyleProperty(aProperty); - // Support other browsers here eventually + if (browserProperty) + _DOMElement.style[browserProperty] = value; } /*! @ignore */ - (BOOL)browserSupportsAnimation { - return typeof(_DOMElement.style.webkitTransition) !== "undefined"; - - /* - No others browsers supported yet. - - typeof(_DOMElement.style.MozTransition) !== "undefined" || - typeof(_DOMElement.style.MsTransition) !== "undefined" || - typeof(_DOMElement.style.OTransition) !== "undefined"; - */ + return CPBrowserStyleProperty('transition') && CPBrowserStyleProperty('transitionend'); } #pragma mark - @@ -452,28 +445,28 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, // Set up the pop-out transition [self setCSS3Property:@"Transform" value:@"scale(1.1)"]; - [self setCSS3Property:@"Transition" value:@"-webkit-transform 200ms ease-in"]; + [self setCSS3Property:@"Transition" value:CPBrowserCSSProperty('transform') + @" 200ms ease-in"]; var transitionEndFunction = function() { - _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES); + _DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES); // Now set up the pop-in to normal size transition. // Because we are watching the -webkit-transform, it will occur now. [self setCSS3Property:@"Transform" value:@"scale(1)"]; - [self setCSS3Property:@"Transition" value:@"-webkit-transform 50ms linear"]; + [self setCSS3Property:@"Transition" value:CPBrowserCSSProperty('transform') + @" 50ms linear"]; var transitionCompleteFunction = function() { - _DOMElement.removeEventListener("webkitTransitionEnd", transitionCompleteFunction, YES); + _DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), transitionCompleteFunction, YES); if (_implementedDelegateMethods & _CPAttachedWindow_attachedWindowDidShow_) [_delegate attachedWindowDidShow:self]; } - _DOMElement.addEventListener("webkitTransitionEnd", transitionCompleteFunction, YES); + _DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), transitionCompleteFunction, YES); }; - _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES); + _DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES); }, 0); } else @@ -506,11 +499,11 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, var transitionEndFunction = function() { - _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES); + _DOMElement.removeEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES); [self _close]; }; - _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES); + _DOMElement.addEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES); } else {