Subversion Repositories JSX

Compare Revisions

Last modification

Ignore whitespace Rev 464 → Rev 465

/trunk/dom/ani.js
15,10 → 15,10
/**
* Retrieves an {@link Array} element as if by the expression
* <code><var>a</var>.slice(<var>index</var>, <var>index</var> + 1)[0]</code>.
*
*
* If <var>index</var> is negative, its absolute is counted
* from the end of <var>a</var>.
*
*
* @param a : Array
* @param index : Number
* @return any
37,7 → 37,7
{
return a[index];
}
 
return a[a.length + index];
};
 
68,7 → 68,7
* {@link jsx.dom.animation#Timeline Timelines} being played in parallel
* when the animation is played. Each <code>Timeline</code> is supposed
* to animate another target object (but that is not required).
*
*
* @param oParams : Object
* The parameters of this animation. Supported parameters, to be defined
* as properties of <var>oParams</var>, include:
89,7 → 89,7
{
jsx.throwThis("jsx.InvalidArgumentError", ["Not enough arguments", typeof oParams, "Object"]);
}
 
for (var param in this)
{
if (typeof oParams[param] != "undefined")
97,19 → 97,19
this[param] = oParams[param];
}
}
 
var timelines = this.timelines;
var _Timeline = jsx.dom.animation.Timeline;
for (var i = timelines.length; i--;)
{
var timeline = timelines[i];
 
if (timeline.constructor != _Timeline)
{
timeline = new _Timeline(timeline);
timelines[i] = timeline;
}
 
if (!timeline.target)
{
timeline.target = this.target;
124,11 → 124,11
*/
target: null,
timelines: [],
 
/**
* Plays the animation by playing all of its
* {@link jsx.dom.animation#Timeline Timelines}.
*
*
* @throws jsx.dom.animation#NoTimelineError
* if no <code>Timelines</code> have been defined
*/
138,17 → 138,17
{
jsx.throwThis("jsx.dom.animation.NoTimelineError");
}
 
for (var i = 0, len = timelines.length; i < len; ++i)
{
timelines[i].play();
}
},
 
/**
* Stops the animation by stopping all of its
* {@link jsx.dom.animation#Timeline Timelines}.
*
*
* @throws Animation.NoTimelineError
* if no <code>Timelines</code> have been defined
*/
158,7 → 158,7
{
jsx.throwThis("jsx.dom.animation.NoTimelineError");
}
 
for (var i = 0, len = timelines.length; i < len; ++i)
{
timelines[i].stop();
178,7 → 178,7
* and can have subordered timelines ("child timelines"). Unless specified
* otherwise, the time offset of an item in one timeline depends on the
* previous item in that timeline.
*
*
* <pre>
* Timeline: ---Action0------Action1------Action2-----Action3->
* </pre>
227,7 → 227,7
keyFrameComparator = function (a, b) {
return a.compareTo(b);
};
 
/**
* @param oParams : Object
*/
236,7 → 236,7
{
jsx.throwThis("jsx.InvalidArgumentError", ["Not enough arguments", typeof oParams, "Object"]);
}
 
var uid = (new Date()).getTime();
this.id = uid;
 
246,26 → 246,26
return this.getCurrentRate();
}
},
 
frameRate: {
get: function () {
return this.getFrameRate();
},
 
set: function (frameRate) {
return this.setFrameRate(frameRate);
}
},
 
id: {
value: uid
}
}, "jsx.dom.animation.Timelime");
 
for (var param in this)
{
var paramValue = oParams[param];
 
if (typeof paramValue != "undefined")
{
if (param == "frameLength" && paramValue < 11)
273,15 → 273,15
paramValue = 11;
jsx.warn("Normalizing frameLength to 11");
}
 
this[param] = paramValue;
}
}
 
/* Sort keyFrames by time */
var keyFrames = this.keyFrames;
var duration = Array.get(keyFrames, -1).time;
 
/* Compute keyframe times that are percentages of the duration */
var rxTimePercentage = /^\s*\+?(\d+|\d*\.\d+)\s*%\s*$/;
var _Frame = jsx.dom.animation.Frame;
289,15 → 289,15
for (var i = 0, len = keyFrames.length; i < len; ++i)
{
var keyFrame = keyFrames[i];
 
if (!(keyFrame instanceof _Frame))
{
keyFrame = new _KeyFrame(keyFrame);
keyFrames[i] = keyFrame;
}
 
keyFrame._timeline = this;
 
// if (len < keyFrames.length - 1)
// {
var time = keyFrame.time;
311,9 → 311,9
}
// }
}
 
keyFrames.sort(keyFrameComparator);
 
// if (this.autoReverse)
// {
// if (keyFrames.length > 0)
342,12 → 342,12
* @type Object
*/
target: null,
 
/**
* @type Array[KeyFrame]
*/
keyFrames: [],
 
/**
* Defines whether this animation reverses direction on alternating cycles.
* If <code>true</code>, the animation will proceed forward on the first
356,7 → 356,7
* initial {@link jsx.dom.animation#KeyFrame KeyFrame}.
*/
autoReverse: false,
 
/**
* Length of a frame in milliseconds (ms). The default value is
* MIN_FRAME_LENGTH so that frames at 0 ms normalized to MIN_TIMEOUT
370,11 → 370,11
* must otherwise be &le; 0.
*/
repeatCount: 1,
 
/**
* Indicates the current direction/speed at which the <code>Timeline</code>
* is being played, in frames per second.
*
*
* @return Number
*/
getCurrentRate: function () {
386,7 → 386,7
* repeats. A <code>Timeline</code> with a <code>repeatCount</code> of
* <code>Timeline.INDEFINITE</code> will have a <code>totalDuration</code>
* of <code>Duration.INDEFINITE</code>.
*
*
* @return {Number}
*/
getTotalDuration: function () {
393,11 → 393,11
return Array.get(this.keyFrames, -1).time * (this.autoReverse ? 2 : 1)
* this.repeatCount;
},
 
/**
* Retrieves the maximum frame rate at which this <code>Timeline</code>
* will play, in frames per second.
*
*
* @return {Number}
*/
getFrameRate: function () {
411,12 → 411,12
* By default, a <code>Timeline</code>'s frame rate is not explicitly
* limited, meaning the <code>Timeline</code> will play at an optimal
* frame rate for the underlying platform.
*
*
* @function
*/
setFrameRate: (function () {
var jsx_dom_animation_Timeline = jsx.dom.animation;
 
/**
* @param frameRate : Number
* The maximum frame rate at which this <code>Timeline</code> will play,
431,7 → 431,7
jsx.info("Cannot change frame rate while playing");
return false;
}
 
/*
* NOTE: Rounding the frame length up and number of frames down
* should help with odd frame lengths/times; frame length not
446,17 → 446,17
+ jsx_dom_animation_Timeline.MIN_FRAME_LENGTH + " ms)");
frameLength = jsx_dom_animation_Timeline.MIN_FRAME_LENGTH;
}
 
this.frameLength = frameLength;
 
return frameLength;
};
}()),
 
/**
* Instructs the <code>Timeline</code> to evaluate all
* <code>KeyValue.value()</code>s in the <code>Timeline</code>.
*
*
* @function
*/
evaluateKeyValues: (function () {
469,17 → 469,17
 
return function () {
var keyFrames = this.keyFrames;
 
for (var i = 1, len = keyFrames.length; i < len; ++i)
{
var nextValues = keyFrames[i].values;
var previousValues = keyFrames[i - 1].values;
 
for (var propertyName in nextValues)
{
var newPropertyValue = nextValues[propertyName];
var oldPropertyValue = previousValues[propertyName];
 
if (propertyName == "style")
{
/* Compute the original values if not given */
488,10 → 488,10
var oldStylePropertyValue = oldPropertyValue[stylePropertyName];
if (typeof oldStylePropertyValue == "undefined")
{
oldStylePropertyValue = _jsx_dom.getComputedStyle(
oldStylePropertyValue = _jsx_dom_css.getComputedStyle(
this.target, null, stylePropertyName);
}
 
var propertyType = _jsx_object.getProperty(
_jsx_dom_css.propertyInfo, stylePropertyName, {type: null}).type;
switch (propertyType)
500,7 → 500,7
if (isNaN(oldStylePropertyValue))
{
oldStylePropertyValue = parseFloat(oldStylePropertyValue);
 
if (isNaN(oldStylePropertyValue))
{
switch (stylePropertyName)
508,7 → 508,7
case "width":
oldStylePropertyValue = this.target.offsetWidth;
break;
 
case "height":
oldStylePropertyValue = this.target.offsetHeight;
break;
516,7 → 516,7
}
}
break;
 
case _jsx_dom_css.types.COLOR:
if (!_jsx_object.isInstanceOf(oldStylePropertyValue, _Color))
{
524,13 → 524,13
}
break;
}
 
if (typeof oldPropertyValue[stylePropertyName] == "undefined")
{
oldPropertyValue[stylePropertyName] = oldStylePropertyValue;
}
}
 
/*
* Set the old style value if the new one was not given.
* NOTE: Objects are _not_ cloned here, but this should not matter.
551,7 → 551,7
}
}
}
 
/* Set old value if the new one was not given */
for (var propertyName in previousValues)
{
566,7 → 566,7
 
/**
* Returns the name of the CSS property for native animation.
*
*
* @function
* @returns {String}
* Returns the first CSS property available for native
582,7 → 582,7
"animation-name", "-moz-animation-name", "-webkit-animation-name"
];
var style = this.target.style;
 
for (var i = 0, len = cssPropertyNames.length; i < len; ++i)
{
var cssPropertyName = cssPropertyNames[i];
592,24 → 592,24
return cssPropertyName;
}
}
 
return result;
};
}()),
 
/**
* Sets the <code>position</code> property of the target
* so that it can be animated.
*
*
* Sets the <code>position</code> property of the target
* to <code>relative</code> if it has been declated to be
* <code>static</code> or not declared at all.
*
*
* @function
*/
_setPosition: (function () {
var _getComputedStyle = jsx.dom.getComputedStyle;
var _getComputedStyle = jsx.dom.css.getComputedStyle;
 
/**
* @param target : Element
*/
620,10 → 620,10
}
};
}()),
 
/**
* Defines a native animation
*
*
* @param animationPropertyName : String
* Name of the animation property, with optional
* vendor-specific prefix.
640,9 → 640,9
}
 
var targetId = target.id;
 
this._setPosition(target);
 
/* FIXME: Reset _here_ has no effect */
var styleId = "jsx-style-" + timelineId;
var style = document.getElementById(styleId);
650,7 → 650,7
{
style.parentNode.removeChild(style);
}
 
style = document.createElement("style");
style.type = "text/css";
style.id = styleId;
659,7 → 659,7
{
prefix += "-";
}
 
style.appendChild(document.createTextNode([
"@" + prefix + "keyframes jsx-timeline-" + timelineId + " {",
this.keyFrames.join("\n"),
672,16 → 672,16
" " + prefix + "animation-timing-function: linear;",
"}"
].join("\n")));
 
var head = document.head || document.getElementsByTagName("head")[0];
head.appendChild(style);
 
return true;
},
 
/**
* Plays this <code>Timeline</code>
*
*
* @function
*/
play: (function () {
693,7 → 693,7
getPropertySetter = function (target, values, bDontPlay, oTimeline) {
return function () {
var setToRelative = false;
 
for (var property in values)
{
if (property == "style")
709,7 → 709,7
oTimeline._setPosition(target);
setToRelative = true;
}
 
_jsx_dom.setStyleProperty(target, styleProperty, style[styleProperty] + "px");
}
else
723,7 → 723,7
target[property] = values[property];
}
}
 
if (bDontPlay)
{
oTimeline._playing = false;
730,29 → 730,29
}
};
};
 
return function () {
/* First clear all remaining timeouts */
this.stop();
 
var nativeProperty = this._getNativeProperty();
if (nativeProperty)
{
return this._playNative(nativeProperty);
}
 
if (!this._keyValuesEvaluated)
{
this.evaluateKeyValues();
this._keyValuesEvaluated = true;
}
 
/* Fix frame length to be integer and long enough */
this.setFrameRate(this.getFrameRate());
var dt = this.frameLength;
 
this._playing = true;
 
for (var i = 1, len = this.keyFrames.length; i < len; ++i)
{
var nextKeyFrame = this.keyFrames[i];
759,7 → 759,7
var previousKeyFrame = this.keyFrames[i - 1];
var previousValues = previousKeyFrame.values;
var nextValues = nextKeyFrame.values;
 
/* Display the previous keyframe, then play the tween */
 
/*
768,10 → 768,10
* frame length not rounded down (faster) to avoid animation stall.
*/
var numFrames = Math.floor((nextKeyFrame.time - previousKeyFrame.time) / dt);
 
var frameValues = _jsx_object.clone(_jsx_object.COPY_ENUM_DEEP, previousValues);
var t = previousKeyFrame.time;
 
var lastFrameIndex = numFrames - 1;
for (var currentFrameIndex = 0;
currentFrameIndex < lastFrameIndex;
785,7 → 785,7
var previousStyle = previousValues.style;
var frameStyle = frameValues.style;
var nextStyle = nextValues.style;
 
for (var styleProperty in frameStyle)
{
interpolate = nextKeyFrame.interpolate;
795,7 → 795,7
nextStyleValue = nextStyleValue.value;
interpolate = nextStyleValue.interpolate;
}
 
frameStyle[styleProperty] = interpolate(
previousStyle[styleProperty],
nextStyleValue,
805,13 → 805,13
else
{
var nextValue = nextValues[property];
 
if (_jsx_object.isInstanceOf(nextValue, jsx.dom.animation.KeyValue))
{
nextValue = nextValue.value;
interpolate = nextValue.interpolate;
}
 
frameValues[property] = interpolate(
previousValues[property],
nextValue,
818,16 → 818,16
currentFrameIndex / numFrames);
}
}
 
this._timeouts.push(
window.setTimeout(
getPropertySetter(this.target,
_jsx_object.clone(_jsx_object.COPY_ENUM_DEEP, frameValues)),
t));
 
t += dt;
}
 
/* Display the last keyframe */
if (i == this.keyFrames.length - 1)
{
839,7 → 839,7
}
};
}()),
 
/**
* Prevents the <code>Timeline</code> from continuing to play.
*/
861,7 → 861,7
* A <code>Frame</code> defines target values at a specified point in time
* for a set of properties of the target object of a
* {@link jsx.dom.animation#Timeline Timeline}.
*
*
* <p>
* This type is usually used only internally to compute the frames between
* a set of given {@link jsx.dom.animation#KeyFrame KeyFrames}.
881,7 → 881,7
*/
jsx.dom.animation.Frame = (function () {
var _getKeys = jsx.object.getKeys;
 
/**
* @param oParams
*/
890,13 → 890,13
{
jsx.throwThis("jsx.InvalidArgumentError", ["Not enough arguments", typeof oParams, "Object"]);
}
 
var keys = _getKeys(oParams);
for (var i = 0, len = keys.length; i < len; ++i)
{
var paramName = keys[i];
var param = oParams[paramName];
 
if (typeof param != "undefined")
{
if (paramName == "time" && typeof param != "number")
918,16 → 918,16
case "ms":
param = +match[1];
break;
 
case "s":
param = +match[1] * 1000;
break;
 
case "m":
case "min":
param = +match[1] * 60000;
break;
 
case "h":
param = +match[1] * 3600000;
break;
939,7 → 939,7
["Invalid time", "'" + param + "'", "one matching " + rxTime.source]);
}
}
 
this[paramName] = param;
}
}
961,13 → 961,13
* to define how time (represented as a (0.0 − 1.0) fraction of the duration
* of an animation) is altered to derive different value calculations during
* an animation.
*
*
* @namespace
*/
jsx.dom.animation.Interpolator = {
/**
* Built-in interpolator that provides linear time interpolation.
*
*
* @function
*/
LINEAR: (function () {
992,7 → 992,7
startValue.blue + (endValue.blue - startValue.blue) * fraction
);
}
 
return startValue + (endValue - startValue) * fraction;
};
}())
1002,7 → 1002,7
* A <code>KeyFrame</code> is a special {@link jsx.dom.animation#Frame Frame} that
* defines target values at a specified point in time for a set of properties
* that are interpolated along a {@link jsx.dom.animation#Timeline Timeline}.
*
*
* The developer controls the interpolation of a set of properties for the
* interval between successive key frames by providing a target value and
* an {@link jsx.dom.animation#Interpolator Interpolator} associated with each
1011,7 → 1011,7
* properties are interpolated such that they will reach their target value
* at the specified time. An <var>action</var> function is invoked on each
* <code>KeyFrame</code> if one is specified.
*
*
* @constructor
* @param oParams
* @throws jsx.InvalidArgumentError if no parameters were specified
1036,13 → 1036,13
compareTo: function (o) {
return this.time - o.time;
},
 
/**
* @memberOf jsx.dom.animation.KeyFrame#prototype
* @function
*/
interpolate: jsx.dom.animation.Interpolator.LINEAR,
 
toString: (function () {
var _jsx_object = jsx.object;
var _getKeys = _jsx_object.getKeys;
1050,7 → 1050,7
var _jsx_dom = jsx.dom;
var _jsx_dom_animation = _jsx_dom.animation;
var _jsx_dom_css = _jsx_dom.css;
 
return function () {
var style = this.values.style;
var keys = _getKeys(style);
1059,7 → 1059,7
{
var stylePropertyName = keys[i];
var propertyValue = style[stylePropertyName];
 
var propertyType = _getProperty(
_jsx_dom_css.propertyInfo, stylePropertyName, {type: null}).type;
switch (propertyType)
1072,16 → 1072,16
var cssPropertyName = stylePropertyName.replace(/[A-Z]/g, function (m) {
return "-" + m.toLowerCase();
});
 
aValues.push(" " + cssPropertyName + ": " + propertyValue + ";");
}
 
var time = this.time + "ms";
if (this._timeline)
{
time = (this.time / Array.get(this._timeline.keyFrames, -1).time * 100) + "%";
}
 
return " " + time + " {\n"
+ aValues.join("\n")
+ "\n }";
1094,7 → 1094,7
{
jsx.throwThis("jsx.InvalidArgumentError", ["Not enough arguments", typeof oParams, "Object"]);
}
 
for (var paramName in this)
{
var param = oParams[paramName];
1110,7 → 1110,7
* {@link jsx.dom.animation#Interpolator} to be used for calculating the
* key value along the particular interval. By default,
* {@link jsx.dom.animation#Interpolator.LINEAR} is used.
*
*
* @memberOf jsx.dom.animation.KeyValue#prototype
*/
interpolate: jsx.dom.animation.Interpolator.LINEAR,
/trunk/dom/css.js
64,7 → 64,8
 
var _LENGTH = 1;
var _COLOR = 5;
var _TRANSFORM = 7;
var _FLOAT = 7;
var _TRANSFORM = 8;
 
return {
/**
145,10 → 146,28
/**
* List of transformations
*/
FLOAT: _FLOAT,
 
/**
* List of transformations
*/
TRANSFORM: _TRANSFORM
},
 
prefixedProperties: {
transition: true,
animation: true
},
 
/**
* Property name prefixes
*/
prefixes: {
camelized: ["Moz", "Ms", "O", "Webkit", ""],
uncamelized: ["-moz-", "-ms-", "-o-", "-webkit-", ""]
},
 
/**
* Provides information about the type of a CSS property and its relation
* to other CSS properties
*
155,16 → 174,49
* @namespace
*/
propertyInfo: {
left: {type: _LENGTH, correspondsTo: "top"},
top: {type: _LENGTH, correspondsTo: "left"},
right: {type: _LENGTH, correspondsTo: "bottom"},
bottom: {type: _LENGTH, correspondsTo: "right"},
width: {type: _LENGTH, correspondsTo: "height"},
height: {type: _LENGTH, correspondsTo: "width"},
color: {type: __COLOR},
backgroundColor: {type: _COLOR},
"background-color": {type: _COLOR},
transform: {type: _TRANSFORM}
"float": {
type: _FLOAT,
aliases: ["cssFloat", "styleFloat"]
},
left: {
type: _LENGTH,
correspondsTo: "top"
},
top: {
type: _LENGTH,
correspondsTo: "left"
},
right: {
type: _LENGTH,
correspondsTo: "bottom"
},
bottom: {
type: _LENGTH,
correspondsTo: "right"
},
width: {
type: _LENGTH,
correspondsTo: "height"
},
height: {
type: _LENGTH,
correspondsTo: "width"
},
color: {
type: _COLOR
},
 
/* FIXME */
backgroundColor: {
type: _COLOR
},
"background-color": {
type: _COLOR
},
 
transform: {
type: _TRANSFORM
}
},
 
/**
262,65 → 314,87
cache.put(sProperty, s2);
return s2;
};
})()
};
})();
})(),
 
/**
* Returns the computed style of an {@link Element} or the
* computed value of an <code>Element</code>'s style property.
*
* @function
*/
jsx.dom.getComputedStyle = (function () {
var _camelize = jsx.dom.css.camelize;
var _getProperty = jsx.object.getProperty;
/**
* Returns the computed style of an {@link Element} or the
* computed value of an <code>Element</code>'s style property.
*
* @function
*/
getComputedStyle: (function () {
var _isMethod = _jsx_object.isMethod;
var _defaultView;
 
var
hasGCS = jsx.object.isMethod(document, "defaultView", "getComputedStyle"),
propertyMap = {
"float": hasGCS ? "cssFloat" : "styleFloat"
};
/**
* @param {Element} oElement
* Element for which the computed style should be retrieved.
* @param {string} sPseudoEl
* The name of the pseudo-element, such as ":first-child".
* Use <code>null</code> (default) for the element itself.
* @param {string} sProperty
* The property name in CSS or script syntax (names are mapped
* automatically according to the feature used). If not passed
* or empty, the entire computed style is returned.
* @return {CSSStyleDeclaration|currentStyle|string|null}
* The return value depends on both the passed arguments
* and the capabilities of the user agent:
*
* If the UA supports either ViewCSS::getComputedStyle()
* from W3C DOM Level 2 CSS or MSHTML's currentStyle
* property, then
* a) if <var>sProperty</var> was passed, the value of the
* CSS property with name <var>sProperty</vr> is returned;
* it is a string if the property is supported;
* b) if <var>cssProperty</var> was not passed, the corresponding
* style object is returned
*
* However, MSHTML's currentStyle does not support pseudo-elements.
* If you attempt to retrieve pseudo-element's computed style,
* <code>null</code> is returned (without error).
*
* If the UA supports neither of the above, <code>null</code>
* is returned.
*/
function _getComputedStyle (oElement, sPseudoEl, sProperty)
{
var computedStyle;
 
/**
* @param {Element} oElement
* Element for which the computed style should be retrieved.
* @param {string} sPseudoEl
* The name of the pseudo-element, such as ":first-child".
* Use <code>null</code> (default) for the element itself.
* @param {string} sProperty
* The property name in CSS or script syntax (names are mapped
* automatically according to the feature used). If not passed
* or empty, the entire computed style is returned.
* @return {CSSStyleDeclaration|currentStyle|string}
*/
function _getComputedStyle (oElement, sPseudoEl, sProperty)
{
if (hasGCS || typeof oElement.currentStyle != "undefined")
{
var compStyle = (hasGCS
? document.defaultView.getComputedStyle(oElement, sPseudoEl || null)
: oElement.currentStyle);
if (_isMethod(document, "defaultView", "getComputedStyle")
&& (typeof _defaultView != "undefined" || (_defaultView = document.defaultView)))
{
computedStyle = _defaultView.getComputedStyle(oElement, sPseudoEl || null);
}
else
{
if (sPseudoEl)
{
return null;
}
 
return (sProperty
? compStyle[
_camelize(
_getProperty(propertyMap, sProperty, sProperty))
]
: compStyle);
}
computedStyle = obj.currentStyle;
}
 
var emptyResult = {};
emptyResult[sProperty] = "";
if (typeof computedStyle != "undefined")
{
if (!sProperty)
{
return computedStyle;
}
 
return (sProperty ? emptyResult : null);
}
return jsx.dom.getStyleProperty({style: computedStyle}, sProperty);
}
 
return _getComputedStyle;
}());
return null;
}
 
return _getComputedStyle;
}())
};
})();
 
/**
* Retrieves the value of a style property of an HTMLElement object.
* Retrieves the value of a style property of an {@link Element}.
*
* @author
* (C) 2005, 2013 Thomas Lahn &lt;js@PointedEars.de&gt;
332,14 → 406,25
var _camelize = jsx.dom.css.camelize;
var _uncamelize = jsx.dom.css.uncamelize;
 
var _prefixedProperties = jsx.dom.css.prefixedProperties;
var _prefixes = jsx.dom.css.prefixes;
var _propertyInfo = jsx.dom.css.propertyInfo;
 
/**
* @param {HTMLElement} oElement
* @param {Element} oElement
* Reference to the element object whose style is to be retrieved.
* @param {String} sPropertyName
* Name of the style property whose value is to be retrieved.
* If "display", and there is no
* <code>style[<var>sPropertyName</var>]</code> property,
* "visibility" is used instead (fallback for the NN4 DOM).
* Both camelCased and dash-property names are supported.
* Mapping to supported prefix properties is done automatically,
* i. e. <code>"transition"</code> would cause
* <code>"-webkit-transition"</code> to be retrieved if
* the former but not <code>"transition"</code> was available.
* If the <code>style</code> property is available on the element,
* the faster property-accessor approach is attempted first,
* then the slower setProperty() call.
* Otherwise <code>"visibility"</code> is used instead
* (fallback for the NN4 DOM).
* @return {string|null}
* <code>null</code> if no matching object exists or if the
* DOM does not provide for retrieval of the property value.
349,55 → 434,86
if (oElement)
{
/* TODO: Needed for NN4 DOM as well? */
var camelizedName = _camelize(sPropertyName);
var camelized_name = _camelize(sPropertyName);
 
if (typeof oElement.style != "undefined")
{
var style = oElement.style;
 
/* Prefer style.getPropertyValue() over mapping to extension properties */
if (_isHostMethod(style, "getPropertyValue"))
var thisPropertyInfo = _propertyInfo[camelized_name];
var thisAliases = thisPropertyInfo && thisPropertyInfo.aliases;
if (thisAliases)
{
sPropertyName = _uncamelize(sPropertyName);
for (var i = thisAliases.length; i--;)
{
var alias = thisAliases[i];
if (typeof style[alias] != "undefined")
{
return style[alias];
}
}
 
return style.getPropertyValue(sPropertyName);
return null;
}
 
/* handle the `float' property */
var isStyleFloat = false;
 
if (camelizedName == "float")
if (_prefixedProperties[sPropertyName])
{
/* W3C DOM Level 2 CSS */
if (typeof style.cssFloat != "undefined")
for (i = _prefixes.camelized.length; i--;)
{
camelizedName = "cssFloat";
isStyleFloat = true;
var prefix = _prefixes.camelized[i];
var prefixed_name = (prefix
? prefix
+ camelized_name.charAt(0).toUpperCase()
+ camelized_name.substring(1)
: camelized_name);
if (typeof style[prefixed_name] != "undefined")
{
return style[prefixed_name];
}
}
 
/* MSHTML DOM */
else if (typeof style.styleFloat != "undefined")
{
camelizedName = "styleFloat";
isStyleFloat = true;
}
return null;
}
 
if (isStyleFloat || typeof style[camelizedName] != "undefined")
if (typeof style[camelized_name] != "undefined")
{
return style[camelizedName];
return style[camelized_name];
}
 
/* If the quick, backwards-compatible method failed for some reason */
if (_isHostMethod(style, "getPropertyValue"))
{
var uncamelized_name = _uncamelize(sPropertyName);
 
/* NOTE: Works because of no dash-properties in _prefixedProperties */
if (_prefixedProperties[sPropertyName])
{
for (i = _prefixes.uncamelized.length; i--;)
{
var value = style.getPropertyValue(
_prefixes.uncamelized[i] + uncamelized_name);
if (value)
{
return value;
}
}
 
return null;
}
 
return style.getPropertyValue(uncamelized_name);
}
}
else
{
if (camelizedName == "display")
if (camelized_name == "display")
{
camelizedName = "visibility";
camelized_name = "visibility";
}
 
if (typeof oElement[camelizedName] != "undefined")
if (typeof oElement[camelized_name] != "undefined")
{
return oElement[camelizedName];
return oElement[camelized_name];
}
}
}
409,7 → 525,7
}());
 
/**
* Determines whether an HTMLElement object has a style property.
* Determines whether an {@link Element} has a style property.
*
* @author
* (C) 2006 Thomas Lahn &lt;js@PointedEars.de&gt;
432,7 → 548,7
};
 
/**
* Sets the value of a style property of an HTMLElement object.
* Sets the value of a style property of an {@link Element}.
*
* @function
* @author
445,26 → 561,38
var _camelize = jsx.dom.css.camelize;
var _uncamelize = jsx.dom.css.uncamelize;
 
var _prefixedProperties = jsx.dom.css.prefixedProperties;
var _prefixes = jsx.dom.css.prefixes;
var _propertyInfo = jsx.dom.css.propertyInfo;
 
/**
* @param {HTMLElement} oElement
* Reference to the element object which style is to be modified.
* @param {Element} oElement
* Reference to the element object whose style is to be modified.
* @param {string} sPropertyName
* Name of the style property of which the value should be set.
* If "display" and there is no <code>style[<var>sPropertyName</var>]</code>
* property and <code>altValue</code> was provided, "visibility" is used
* instead (fallback for the NN4 DOM).
* Name of the style property whose value should be set.
* Both camelCased and dash-property names are supported.
* Mapping to supported prefix properties is done automatically,
* i. e. <code>"transition"</code> would cause only
* <code>"-webkit-transition"</code> to be set if the former
* but not <code>"transition"</code> was available.
* If the <code>style</code> property is available on the element,
* the faster property-accessor approach is attempted first,
* then the slower setProperty() call.
* If <code>"display"</code>, and there is no <code>style</code>
* property, and <code>altValue</code> was provided, "visibility"
* is used instead (fallback for the NN4 DOM).
* @param propValue
* Value of the style property to be set.
* @param {_} altValue (optional)
* Alternative value to be set if the the style property is a property of
* the object itself instead of its `style' property. Fallback for the
* NN4 DOM.
* Alternative value to be set if the the style property is a
* property of the object itself instead of its `style' property.
* Fallback for the NN4 DOM.
* @return {boolean}
* <code>false</code> if no such object exists, the
* DOM does not provide for setting the property value,
* or if the assignment failed (invalid value).
* CAVEAT: Some property values are normalized by the API when read;
* test before using the return value as a discriminator.
* CAVEAT: Some property values are normalized by the DOM API
* when read; test before using the return value as a discriminator.
*/
function _setStyleProperty (oElement, sPropertyName, propValue, altValue)
{
471,56 → 599,84
if (oElement)
{
/* TODO: Needed for NN4 DOM as well? */
var camelizedName = _camelize(sPropertyName);
var camelized_name = _camelize(sPropertyName);
 
if (typeof oElement.style != "undefined")
{
var style = oElement.style;
 
/* Prefer style.setProperty() over mapping to extension properties */
if (_isHostMethod(style, "setProperty"))
var thisPropertyInfo = _propertyInfo[camelized_name];
var thisAliases = thisPropertyInfo && thisPropertyInfo.aliases;
if (thisAliases)
{
sPropertyName = _uncamelize(sPropertyName);
for (var i = thisAliases.length; i--;)
{
var alias = thisAliases[i];
if (typeof style[alias] != "undefined")
{
style[alias] = propValue;
return (String(style[alias]).toLowerCase()
== String(propValue).toLowerCase());
}
}
 
style.setProperty(sPropertyName, propValue);
return false;
}
 
if (!_isHostMethod(style, "getPropertyValue"))
if (_prefixedProperties[sPropertyName])
{
var len;
for (i = 0, len = _prefixes.camelized.length; i < len; ++i)
{
return true;
var prefix = _prefixes.camelized[i];
var prefixed_name = (prefix
? prefix
+ camelized_name.charAt(0).toUpperCase()
+ camelized_name.substring(1)
: camelized_name);
if (typeof style[prefixed_name] != "undefined")
{
style[prefixed_name] = propValue;
}
}
 
return (String(style.getPropertyValue(sPropertyName)).toLowerCase()
== String(propValue).toLowerCase());
return (String(style[prefixed_name]).toLowerCase()
== String(propValue).toLowerCase());
}
 
/* handle the `float' property */
var isStyleFloat = false;
if (typeof style[camelized_name] != "undefined")
{
style[camelized_name] = propValue;
return (String(style[camelized_name]).toLowerCase()
== String(propValue).toLowerCase());
}
 
if (camelizedName == "float")
/* If the quick, backwards-compatible method failed for some reason */
if (_isHostMethod(style, "setProperty"))
{
/* W3C DOM Level 2 CSS */
if (typeof style.cssFloat != "undefined")
var uncamelized_name = _uncamelize(sPropertyName);
 
/* NOTE: Works because of no dash-properties in _prefixedProperties */
if (_prefixedProperties[sPropertyName])
{
camelizedName = "cssFloat";
isStyleFloat = true;
}
for (i = 0, len = _prefixes.uncamelized.length; i < len; ++i)
{
style.setProperty(
_prefixes.uncamelized[i] + uncamelized_name,
propValue);
}
 
/* MSHTML DOM */
else if (typeof style.styleFloat != "undefined")
{
camelizedName = "styleFloat";
isStyleFloat = true;
if (!_isHostMethod(style, "getPropertyValue"))
{
return true;
}
 
return (String(style.getPropertyValue(sPropertyName)).toLowerCase()
== String(propValue).toLowerCase());
}
}
 
if (isStyleFloat || typeof style[camelizedName] != "undefined")
{
/*
* NOTE: Shortcut evaluation changed behavior;
* result of assignment is *right-hand side* operand
*/
style[camelizedName] = propValue;
return (String(style[camelizedName]).toLowerCase()
style.setProperty(uncamelized_name, propValue);
return (String(style.getPropertyValue(uncamelized_name)).toLowerCase()
== String(propValue).toLowerCase());
}
}
527,16 → 683,16
else
{
/* NN4 DOM */
if (camelizedName == "display" && altValue)
if (camelized_name == "display" && altValue)
{
camelizedName = "visibility";
camelized_name = "visibility";
}
 
if (typeof oElement[camelizedName] != "undefined")
if (typeof oElement[camelized_name] != "undefined")
{
var newValue = (altValue || propValue);
oElement[camelizedName] = newValue;
return (String(oElement[camelizedName]).toLowerCase()
oElement[camelized_name] = newValue;
return (String(oElement[camelized_name]).toLowerCase()
== String(newValue).toLowerCase());
}
}
1018,63 → 1174,6
}());
 
/**
* Returns the computed style of an element or
* the computed value of a style property of an element.
*/
jsx.dom.css.getComputedStyle = (function () {
var _isMethod = jsx.object.isMethod,
_defaultView;
 
/**
* @param {Element} obj
* @param {string} cssProperty
* @return {CSSStyleDeclaration|string}
* The return value depends on both the passed arguments
* and the capabilities of the user agent:
*
* If the UA supports either ViewCSS::getComputedStyle()
* from W3C DOM Level 2 CSS or MSHTML's currentStyle
* property, then
* a) if <var>cssProperty</var> was passed, the value of the
* CSS property with name <var>cssProperty</vr> is returned;
* it is a string if the property is supported;
* b) if <var>cssProperty</var> was not passed, the corresponding
* style object is returned
*
* If the UA supports neither of the above, `undefined' is
* returned.
* @type string|CSSStyleDeclaration|currentStyle
*/
return function (obj, cssProperty) {
var computedStyle;
 
if (_isMethod(document, "defaultView", "getComputedStyle")
&& (typeof _defaultView != "undefined" || (_defaultView = document.defaultView))
&& (computedStyle = _defaultView.getComputedStyle(obj, null)))
{
if (cssProperty)
{
if (_isMethod(computedStyle, "getPropertyValue"))
{
return computedStyle.getPropertyValue(cssProperty);
}
 
return jsx.throwThis(null, "Unable to retrieve computed style property");
}
}
else if (typeof (computedStyle = obj.currentStyle) != "undefined")
{
if (cssProperty)
{
return computedStyle[cssProperty];
}
}
 
return computedStyle;
};
}());
 
/**
* Makes all non-default stylesheet declarations for an element inline
*/
jsx.dom.css.makeInline = (function () {