From: Andrew Poulos on
How do I get the opacity value in IE where the opacity is set via a
filter eg.

<img style="filter:alpha(opacity=12);" src="... >

Andrew Poulos
From: Garrett Smith on
Andrew Poulos wrote:
> How do I get the opacity value in IE where the opacity is set via a
> filter eg.
>
> <img style="filter:alpha(opacity=12);" src="... >

This was discussed not too long ago, related to Gregor's library.

The common saying: "Google is your friend" does not hold true here.

Here's what I do:

Excerpted from APE[1]:

var alphaOpExp = /\Wopacity\s*=\s*([\d]+)/i;

/* |cs| is an IE currentStyle object. */
function getFilterOpacity(cs) {
var o, f = cs.filter;
if(!alphaOpExp.test(f)) return 1;
o = alphaOpExp.exec(f);
return o[1]/100;
}

Why do I say "Google is your friend" does not hold true here?

Google Closure style.js
http://closure-library.googlecode.com/svn/trunk/closure/goog/style/style.js
/**
* Gets the opacity of a node (x-browser). This gets the inline style
* opacity of the node, and does not take into account the cascaded or
* the computed style for this node.
* @param {Element} el Element whose opacity has to be found.
* @return {number|string} Opacity between 0 and 1 or an empty string
* {@code ''} if the opacity is not set.
*/
goog.style.getOpacity = function(el) {
var style = el.style;
var result = '';
if ('opacity' in style) {
result = style.opacity;
} else if ('MozOpacity' in style) {
result = style.MozOpacity;
} else if ('filter' in style) {
var match = style.filter.match(/alpha\(opacity=([\d.]+)\)/);
if (match) {
result = String(match[1] / 100);
}
}
return result == '' ? result : Number(result);
};

This function works only for inline style, fails in IE even for that.

The result of calling String(match[1] / 100); is pointless as |result|
is converted to number.

The numeric conversion can be more efficiently
achieved by using unary + operator.

The variant return type returns string, if the opacity is not set in the
element's inline style. I cannot understand why the API would want to
require opacity to be set in ElementCSSInlineStyle (or IE equivalent
inline style property) and knowingly failing to return the element's
opacity when set in a cascading stylesheet. Doesn't style information
belong in the stylesheet?

The function will fail if there is any whitespace in the element's
filter string, or if the filter string uses proper case, (and examples
on MSDN do).

<div id="x" style="filter: alpha( Opacity = 10 )">hey hey, goodbye</div>

var x = document.getElementById("x")
goog.style.getOpacity(x);

Will fail to get the opacity in IE.

This function does not read from currentStyle; only inline style.

For reading currentStyle, Google Closure provides:

goog.style.getStyle_ = function(element, style) {
return goog.style.getComputedStyle(element, style) ||
goog.style.getCascadedStyle(element, style) ||
element.style[style];
};

goog.style.getStyle_ calls goog.style.getCascadedStyle, which uses IEs
currentStyle property:

goog.style.getCascadedStyle = function(element, style) {
return element.currentStyle ? element.currentStyle[style] : null;
};

Method goog.style.getStyle_ fails to read "opacity" in IE because no
versions of IE (IE8 is the latest) support the CSS3 "opacity" style
property. That function mightwork for IE9, should IE decide to provide
support of CSS3, though IE supporting CSS3 in a currentStyle should be
thought out carefully.

The naming of getStyle_ uses a trailing underscore. This is apparently
to make the function "fake private". Instead, a closure could have been
used. If a closure had been used, the identifier could be hidden in
scope and made publicly available. This is arguably better design as it
simplifies the public interface of goog.style (not having an extra
object exposed to the API). Regardless of the design nit, the code will
fail to read opacity in so many cases that changing that at this point
would miss the point (would still be broken).

Ironic that the Google Closure library uses fake private in code instead
of using actual closures.

Using closures can result in simpler API, faster performance by using
in-scope variables, and more munging (local identifiers can be munged)
resulting in smaller file size.

Knowing how to use closures, one can write code that is faster, smaller,
have a simplified interface.

Google has, in the past, justified using Global identifiers with
performance, however it has been shown that Global identifiers are not
resolved more quickly, except for in Firefox 3.5 (and that is due to an
internal optimization which may in the future, apply to non-global
containing scope).

I cannot justify the design decision of fake private; but see benefits
to using a closure based approach:
* smaller - no long namespace + "_" for "fake private", more munging.
* faster - local variables are resolved faster
* simplified interface - no fake private.

[1]http://github.com/GarrettS/ape-javascript-library/blob/master/src/dom/style-f.js#L32
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Garrett Smith on
Garrett Smith wrote:
> Andrew Poulos wrote:
>> How do I get the opacity value in IE where the opacity is set via a
>> filter eg.
>>

[...]

> if (match) {
> result = String(match[1] / 100);
> }
> }
> return result == '' ? result : Number(result);
> };
>
> This function works only for inline style, fails in IE even for that.
>
> The result of calling String(match[1] / 100); is pointless as |result|
> is converted to number.
>
Ah, no sorry, that does make a difference if the result is "0".

"0" / 100 results in 0 (number).

Since 0 == '', the result would be returned then.

A strict equality test seems less confusing.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Thomas 'PointedEars' Lahn on
Andrew Poulos wrote:

> How do I get the opacity value in IE where the opacity is set via a
> filter eg.
>
> <img style="filter:alpha(opacity=12);" src="... >

imgRef.filters.item("alpha").opacity

Garrett is wrong, STFW for "filter:alpha(opacity" would have helped.
The MSDN Library entry is the first hit here:

<http://msdn.microsoft.com/en-us/library/ms532967(VS.85).aspx>

It contains a link to "Scripting Filters" at the bottom.


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
From: Garrett Smith on
Thomas 'PointedEars' Lahn wrote:
> Andrew Poulos wrote:
>
>> How do I get the opacity value in IE where the opacity is set via a
>> filter eg.
>>
>> <img style="filter:alpha(opacity=12);" src="... >
>
> imgRef.filters.item("alpha").opacity
>
> Garrett is wrong, STFW for "filter:alpha(opacity" would have helped.
> The MSDN Library entry is the first hit here:
>

That suggestion will result in error when the filter object is
undefined or uses the recommended DXImageTransform filter instead of
just alpha.

This is a problem because it is undefined when not set:

QUick example:
javascript: alert(document.body.style.filters.item("alpha"))

It is a more significant problem when the advice on MSDN is followed:
> <http://msdn.microsoft.com/en-us/library/ms532967(VS.85).aspx>
>
<msdn comment>
That MSDN page is unusable in IE7. When scrolling the window. the
content in the body stays fixed and the navigation scrolls.

There doesn't seem to be a way to switch to script free view. I remember
a javascript: button at the botttom of the page, but cannot scroll to
reach it in IE7.

Launching in Opera, I get script free, with no parameter. Then, clicking
lightweight, I get the option to switch to "ScriptFree", which does
contain the "loband" parameter.

OK, now that I can view the page, back to the discussion...
</msdn comment>
> It contains a link to "Scripting Filters" at the bottom.
>
http://msdn.microsoft.com/en-us/library/ms532847(VS.85,loband).aspx

Suggests using the DXImageTransform filter instead. Example:

el.filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);

That works great. The problem is when trying to read the filter using
the approach el.filters.item("alpha").opacity.

The result is an error is produced.

There are two alpha filters:

filter: alpha(opacity = 10);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 10);

The latter is being changed now to follow CSS 2.1 Syntax:
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=52)"

http://blogs.msdn.com/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx

<sarcasm>
Thanks, Microsoft. I really needed one more way to set the filter.
</sarcasm>

Conclusion:
By parsing the filter string, either type of alpha filter can be read.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/