IE and the Opacity

Discussion in 'Javascript' started by Defacta, Oct 4, 2007.

  1. Defacta

    Defacta Guest

    Hi!

    This works fine with Firefox and Safari but with IE, IE tells me
    Object required, here is the code:

    var max = 100;
    var min = 0;
    var opacite=min;
    up=true;
    var IsIE=!!document.all;
    var ThePic=document.getElementById("fact-content");

    function fadePic(){
    if (opacite<max && up){opacite+=3;}
    if (opacite>min && !up){opacite-=3;}
    if (opacite>=max){up=false;}
    if (opacite<=min){up=true;}

    IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    content").style.opacity=opacite/100;
    document.getElementById('fact-content').value=opacite+"%"
    }
    setInterval(function(){fadePic();},50)


    function Opacificateur(Obj,quantite) {
    Obj.style.opacity = quantite/10;
    Obj.style.filter = 'alpha(opacity=' + quantite*10 + ')';
    }

    The IE error is for that line:
    IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    content").style.opacity=opacite/100;

    What can I do ?

    Thanks,
    Vincent.

    PS: fact-content is not image but a div like this:

    <div id="fact-content" style="filter:alpha(opacity=100);-moz-opacity:
    1; ">
    Hello world !
    </div>
     
    Defacta, Oct 4, 2007
    #1
    1. Advertising

  2. On Oct 4, 8:42 am, Defacta <> wrote:
    > This works fine with Firefox and Safari but with IE, IE tells me
    > Object required, here is the code:
    >
    > var max = 100;
    > var min = 0;
    > var opacite=min;


    Try to rework this using no global variables, instead attaching all
    variables as properties of a single global object (in JavaScript
    parlance, a "namespace". A misnomer, but still useful). You'll thank
    yourself if, next year, you're re-writing or extending this code and
    need to know where everything comes from.


    > up=true;


    Use "var" to declare all variables.

    > var IsIE=!!document.all;


    You don't want to do this browser sniffing. It's highly error-prone.
    There are better ways. See below.

    > var ThePic=document.getElementById("fact-content");


    You also don't want DOM element references lurking around in global
    variables. See: http://www.jibbering.com/faq/faq_notes/closures.html

    >
    > function fadePic(){
    > if (opacite<max && up){opacite+=3;}
    > if (opacite>min && !up){opacite-=3;}
    > if (opacite>=max){up=false;}
    > if (opacite<=min){up=true;}
    >
    > IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    > content").style.opacity=opacite/100;
    > document.getElementById('fact-content').value=opacite+"%"}


    Try:

    if (ThePic.filters) {
    ThePic.style.filter = 'alpha(opacity='+opacite+')';
    } else {
    ThePic.style.opacity = opacite/100;
    }

    The "filters" collection is a nonstandard HTMLElement attribute, so it
    will tell you if the element in question supports filtering.
    Otherwise, you shouldn't need to bother with setting the value through
    the "filters" collection. Google "Peter Michaux Lazy Function
    Definition" to figure out how to run this test only once (so it
    doesn't slow down an animation, for example).

    >
    > setInterval(function(){fadePic();},50)


    More concisely, without the closure:

    window.setInterval(fadePic, 50);

    >
    > function Opacificateur(Obj,quantite) {
    > Obj.style.opacity = quantite/10;
    > Obj.style.filter = 'alpha(opacity=' + quantite*10 + ')';
    >
    > }


    Did you try this by itself? Why the duplicate code?

    >
    > The IE error is for that line:
    > IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    > content").style.opacity=opacite/100;
    > PS: fact-content is not image but a div like this:
    >
    > <div id="fact-content" style="filter:alpha(opacity=100);-moz-opacity:
    > 1; ">


    You shouldn't ever need to use the proprietary style "-moz-opacity";
    Mozilla automatically translates "opacity" into that for you.

    -David
     
    David Golightly, Oct 5, 2007
    #2
    1. Advertising

  3. Defacta

    David Mark Guest

    On Oct 4, 11:42 am, Defacta <> wrote:
    > Hi!
    >
    > This works fine with Firefox and Safari but with IE, IE tells me
    > Object required, here is the code:
    >

    [snip]

    Search this group for a recent post about feature testing opacity
    support.
     
    David Mark, Oct 5, 2007
    #3
  4. David Golightly wrote:
    > On Oct 4, 8:42 am, Defacta <> wrote:
    >> This works fine with Firefox and Safari but with IE, IE tells me
    >> Object required, here is the code:
    >>
    >> var max = 100;
    >> var min = 0;
    >> var opacite=min;

    >
    > Try to rework this using no global variables, instead attaching all
    > variables as properties of a single global object


    The term "global object" here is misleading, as there is already a built-in
    Global Object. "Globally available object" is more feasible, which
    describes what you apparently meant: a globally available identifier that
    serves as a reference to an object.

    > (in JavaScript parlance, a "namespace".


    Maybe in *your* parlance, and other clueless library lemmings out there.

    > A misnomer,


    Indeed it is.

    > but still useful).


    It isn't. The concept of namespaces was introduced into the language not
    before ECMAScript Edition 4, which is currently only a working draft, and
    has only one implementation ready for production use (for fitting values
    of "ready"): JScript .NET, (AFAIK) server-side (IIS-)only.

    >> var ThePic=document.getElementById("fact-content");

    >
    > You also don't want DOM element references lurking around in global
    > variables.


    Why not? Sometimes there is no better way to avoid looking up a DOM object
    reference repeatedly.

    > See: http://www.jibbering.com/faq/faq_notes/closures.html


    Non sequitur. Closures are created by *local* execution contexts.

    >> function fadePic(){
    >> if (opacite<max && up){opacite+=3;}
    >> if (opacite>min && !up){opacite-=3;}
    >> if (opacite>=max){up=false;}
    >> if (opacite<=min){up=true;}
    >>
    >> IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    >> content").style.opacity=opacite/100;
    >> document.getElementById('fact-content').value=opacite+"%"}

    >
    > Try:
    >
    > if (ThePic.filters) {
    > ThePic.style.filter = 'alpha(opacity='+opacite+')';


    Wrong. The MSDN Library explains how to do it properly:

    http://msdn2.microsoft.com/en-us/library/ms532847.aspx

    > } else {
    > ThePic.style.opacity = opacite/100;
    > }
    >
    > The "filters" collection is a nonstandard HTMLElement attribute,


    Utter nonsense. The HTMLElement interface is part of the W3C DOM Level 2
    HTML *Web standard*.

    `filters' is a proprietary *property* of HTML element objects in the MSHTML
    DOM. It *is* a reference to a collection, though.

    >> setInterval(function(){fadePic();},50)

    >
    > More concisely, without the closure:
    >
    > window.setInterval(fadePic, 50);


    Which can change the meaning of `this' within `fadePic' significantly.

    Obviously you have little to no clue what you are talking about.

    >> function Opacificateur(Obj,quantite) {
    >> Obj.style.opacity = quantite/10;
    >> Obj.style.filter = 'alpha(opacity=' + quantite*10 + ')';
    >>
    >> }

    >
    > Did you try this by itself? Why the duplicate code?


    It is a simple, yet error-prone way to satisfy at least two DOMs (all DOMs
    that implement the CSSStyleDeclaration interface for the `style' property,
    and the MSHTML DOM). It is error-prone because `Obj.style' refers to an
    host object that does not need to support the addition of properties.

    >> PS: fact-content is not image but a div like this:
    >>
    >> <div id="fact-content" style="filter:alpha(opacity=100);-moz-opacity:
    >> 1; ">

    >
    > You shouldn't ever need to use the proprietary style "-moz-opacity";
    > Mozilla automatically translates "opacity" into that for you.


    It only does so since about 2005-02-20 12:55:08 PDT.

    https://bugzilla.mozilla.org/show_bug.cgi?id=281907


    PointedEers
    --
    "Use any version of Microsoft Frontpage to create your site. (This won't
    prevent people from viewing your source, but no one will want to steal it.)"
    -- from <http://www.vortex-webdesign.com/help/hidesource.htm>
     
    Thomas 'PointedEars' Lahn, Oct 5, 2007
    #4
  5. Thomas 'PointedEars' Lahn wrote:
    > David Golightly wrote:
    >> On Oct 4, 8:42 am, Defacta <> wrote:
    >>> IsIE?ThePic.filters[0].opacity=opacite:document.getElementById("fact-
    >>> content").style.opacity=opacite/100;
    >>> document.getElementById('fact-content').value=opacite+"%"}

    >> Try:
    >>
    >> if (ThePic.filters) {
    >> ThePic.style.filter = 'alpha(opacity='+opacite+')';

    >
    > Wrong. The MSDN Library explains how to do it properly:
    >
    > http://msdn2.microsoft.com/en-us/library/ms532847.aspx


    Ignore that, my bad. As also described in the MSDN Library, it is indeed
    "correct" if the `style' attribute of the corresponding element does not
    include a `filter' declaration yet (which would be good because that style
    property is proprietary and including it in the first place would make the
    CSS not Valid). Sorry, I confused that with scripting already declared filters.


    PointedEars
    --
    var bugRiddenCrashPronePieceOfJunk = (
    navigator.userAgent.indexOf('MSIE 5') != -1
    && navigator.userAgent.indexOf('Mac') != -1
    ) // Plone, register_function.js:16
     
    Thomas 'PointedEars' Lahn, Oct 5, 2007
    #5
  6. On Oct 5, 6:44 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > David Golightly wrote:
    > > On Oct 4, 8:42 am, Defacta <> wrote:
    > >> setInterval(function(){fadePic();},50)

    >
    > > More concisely, without the closure:

    >
    > > window.setInterval(fadePic, 50);

    >
    > Which can change the meaning of `this' within `fadePic' significantly.
    >
    > Obviously you have little to no clue what you are talking about.


    How does that work, exactly? In what way is the value of "this"
    changed within "fadePic", and to what does it now refer (in each
    case)? Could you please explain this mechanism to me? I would very
    much like to get it right.

    -David
     
    David Golightly, Oct 6, 2007
    #6
  7. David Golightly wrote:
    > [...] Thomas 'PointedEars' Lahn [...] wrote:
    >> David Golightly wrote:
    >>> On Oct 4, 8:42 am, Defacta <> wrote:
    >>>> setInterval(function(){fadePic();},50)
    >>> More concisely, without the closure:


    I don't think there is a closure here: `fadePic' is not resolved before
    the function argument is called. Not every function expression creates
    a closure.

    http://en.wikipedia.org/wiki/Closure_(computer_science)

    >>> window.setInterval(fadePic, 50);

    >> Which can change the meaning of `this' within `fadePic' significantly.
    >>
    >> Obviously you have little to no clue what you are talking about.

    >
    > How does that work, exactly? In what way is the value of "this"
    > changed within "fadePic", and to what does it now refer (in each
    > case)? Could you please explain this mechanism to me? I would very
    > much like to get it right.


    Why, you could simply test it.

    `this' in a method refers to the calling object.

    I was referring to `fadePic' as an example, hence the "can". It will
    probably not change anything here because `fadePic' is probably called
    as a method of the same object in the scope chain.

    But if you use for example

    var o = {
    fadePic: function()
    {
    window.alert(this);
    }
    };

    // and then

    window.setTimeout(o.fadePic, 50) // [1]

    // instead of

    window.setTimeout(function() { o.fadePic(); }, 50)

    that changes the meaning of `this' in the method o.fadePic is a reference
    to. In the former case it would probably refer to the object setTimeout()
    is called as a method of; in the latter case it would refer to the same
    object as `o'.

    My point being was/is that these two approaches are not generally
    equivalent, and that avoiding (supposed) closures is not always the best
    approach.


    PointedEars
    ___________
    [1] It is the same with setInterval() or any other call, but setTimeout()
    serves better as a similar example to the OP's code.
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
     
    Thomas 'PointedEars' Lahn, Oct 6, 2007
    #7
  8. On Oct 6, 10:55 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > David Golightly wrote:
    > > [...] Thomas 'PointedEars' Lahn [...] wrote:
    > >> David Golightly wrote:
    > >>> On Oct 4, 8:42 am, Defacta <> wrote:
    > >>>> setInterval(function(){fadePic();},50)
    > >>> More concisely, without the closure:

    >
    > I don't think there is a closure here: `fadePic' is not resolved before
    > the function argument is called. Not every function expression creates
    > a closure.
    >
    > http://en.wikipedia.org/wiki/Closure_(computer_science)


    According to the Wikipedia article, "a closure is a function that is
    evaluated in an environment containing one or more bound variables.
    When called, the function can access these variables." In this
    instance, the anonymous function being passed to window.setTimeout as:

    function doStuff() {
    var o = {};
    window.setTimeout(function () { fadePic(); }, 50);
    }

    has access to the variable "o" which is local to the containing
    function "doStuff", hence, a closure. However, in the OP's example
    (which is itself presumably wrapped in a function he neglected to
    copy, or should be), none of those variables are used, except
    "fadePic" itself. Since a closure is not needed here, I recommend not
    using it; fadePic is itself a function that is not a property of any
    object but the Global object, so the value of "this" is unchanged,
    regardless of whether it is called within an anonymous function or
    called directly.

    >
    > >>> window.setInterval(fadePic, 50);
    > >> Which can change the meaning of `this' within `fadePic' significantly.

    >
    > >> Obviously you have little to no clue what you are talking about.

    >
    > > How does that work, exactly?

    >
    > Why, you could simply test it.
    >
    > `this' in a method refers to the calling object.
    >
    > I was referring to `fadePic' as an example, hence the "can". It will
    > probably not change anything here because `fadePic' is probably called
    > as a method of the same object in the scope chain.


    In this example, we can drop the word "probably". Since "fadePic" is
    not being called as a property of a local object, its "this" value
    points to the Global object anyway.

    >
    > But if you use for example
    >
    > var o = {
    > fadePic: function()
    > {
    > window.alert(this);
    > }
    > };
    >
    > // and then
    >
    > window.setTimeout(o.fadePic, 50) // [1]
    >
    > // instead of
    >
    > window.setTimeout(function() { o.fadePic(); }, 50)
    >
    > that changes the meaning of `this' in the method o.fadePic is a reference
    > to. In the former case it would probably refer to the object setTimeout()
    > is called as a method of; in the latter case it would refer to the same
    > object as `o'.
    >
    > My point being was/is that these two approaches are not generally
    > equivalent, and that avoiding (supposed) closures is not always the best
    > approach.


    That's a valid distinction, but understanding it is central to
    effective JavaScript. What's necessary in the latter case -
    preserving the object "o" within the scope chain, so that its property
    "fadePic" may be called at a later time - is not necessary in the
    former case. However, the latter example brings problems of its own,
    as I've seen lots of beginners try:

    function Foo() {}

    Foo.prototype.doBar = function () { /* stuff here */ };
    Foo.prototype.delayedBar = function () { window.setTimeout(function ()
    { this.doBar() }, 50); };

    var foo = new Foo();
    foo.delayedBar();

    which gives a syntax error, since the Global object has no method
    "doBar". Likewise,

    Foo.prototype.delayedBar = function () { window.setTimeout(this.doBar,
    50); };

    will pass in a function, but as you say, its "this" will refer to the
    Global object, not the object that inherits from Foo.prototype. The
    (most likely) intended behavior, not immediately obvious to beginners,
    is:

    Foo.prototype.delayedBar = function () { var foo = this;
    window.setTimeout(function () { foo.doBar() }, 50); };

    I would, in general, discourage use of closures unless they're needed
    for a specific, premeditated purpose; a recurring setInterval call
    will preserve the scoped local variables in memory long after the
    original function has returned and there is no longer a need for
    them. When they are needed, it's a good idea to attempt to limit the
    scope to prevent or at least minimize unintended memory leaks.

    To sum up, it seems the best rule of thumb is to simply learn the
    rules, and decide which technique to use based on what's needed in a
    particular context.

    -David
     
    David Golightly, Oct 6, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. DU
    Replies:
    13
    Views:
    946
  2. Replies:
    1
    Views:
    437
    Adrienne Boswell
    May 25, 2007
  3. Replies:
    0
    Views:
    630
  4. Mark B

    DropDownListBox and Opacity

    Mark B, Jun 30, 2003, in forum: Javascript
    Replies:
    0
    Views:
    92
    Mark B
    Jun 30, 2003
  5. mhoeneveld

    Image opacity and

    mhoeneveld, May 2, 2006, in forum: Javascript
    Replies:
    0
    Views:
    94
    mhoeneveld
    May 2, 2006
Loading...

Share This Page