CSS3 PIE Forums

Extending CSS3 Pie
Page 1 of 1

Author:  mario [ Thu Feb 10, 2011 8:09 am ]
Post subject:  Extending CSS3 Pie

Hey there,

I've recently started to use CSS3 Pie in a custom Javascript enviroment. However, the only thing I miss is to be able to use transparency set via "filter=alpha(..." (like jQuery does for animations). I came across the ticket at https://github.com/lojjic/PIE/issues/issue/46 and thought about extending it by myself. Of course I'll provide the changes for you.

However, I'm facing some problems.
I did the following changes on PIE.htc:

1. Added a listener (addListener) in PIE.Element.init
2. This listener invokes a method in PIE.Element on "onfilterchange"
3. This method checks some parameters and invokes a new method in the elements RootRenderer
4. This method sets the new opacity to the element

According to what I saw in your code, this should be the correct way of handling attributes, that might change. However, onfilterchange (which is officially supportet by IE) doesn't seem to get fired at all.

Is the element 'el' within PIE.Element's init referring to the original element, where PIE.htc is attached to? Or is it some sort of copy?
For debugging reasons, I was outputting the filter attribute of the element "el" within PIE.Element.propChanged and saw the filter-attribute to be changed. However, I'm a bit confused by the different ways "el" is used.

Could you please push me into the right direction? Is PIE.Element.init.el a dummy/clone object? Do I need to push the original's filter attribute to that element?

Here's some code:
(i've left the line numbers, so you can track it down if you want)
3271                 if( !eventsAttached ) {
3272                     eventsAttached = 1;
3273                     addListener( el, 'onmove', handleMoveOrResize );
3274                     addListener( el, 'onresize', handleMoveOrResize );
3275                     addListener( el, 'onpropertychange', propChanged );
3276                     addListener( el, 'onmouseenter', mouseEntered );
3277                     addListener( el, 'onmouseleave', mouseLeft );
3278                     addListener( el, 'onfilterchange', filterChanged );
3279                     PIE.OnResize.observe( handleMoveOrResize );
3281                     PIE.OnBeforeUnload.observe( removeEventListeners );
3282                 }

3165 PIE.Element = (function() {
3400         function filterChanged() {
3401             alert("FILTER CHANGED!");
3402             if( !destroyed ) {
3403                 if( initialized ) {
3404                     var i, len;
3406                     lockAll();
3407                     for( i = 0, len = renderers.length; i < len; i++ ) {
3408                         renderers[i].updateFilter();
3409                     }
3410                     unlockAll();
3411                 }
3412                 else if( !initializing ) {
3413                     init();
3414                 }
3415             }
3416         }

2020 PIE.RootRenderer = PIE.RendererBase.newRenderer( {
2097     updateFilter: function() {
2098         var el = this.getPositioningElement();
2099         alert(el.style.filter);
2100         // <Do lots of fancy filter handling stuff on el>
2101     },

I've left out posting removeListener and some other stuff.

Attention, pseudo-code ahead:
My test-case is pretty simple. I've got one #element with PIE.htc attached to it. On onclick I set (#element).style.filter = 'alpha(Opacity=50)';.
I'm sure, PIE works, as I've also set rounded borders to the element. I'm also sure the filter is applied, as its child elements are set to transparent after invoking the filter change. However, "onfilterchange" within PIE.htc is not fired.

I've manually set the #element's onfilterchange to debug some output and so it does when the filter is applied.
Means the event is intact. However, it isn't recognized by PIE.htc.

Thanks for your help.

Kind Regards from Germany

Author:  jason [ Thu Feb 10, 2011 11:45 am ]
Post subject:  Re: Extending CSS3 Pie

I've never used the onfilterchange event before so I don't know if there are any quirks to it. The 'el' var in that context is the actual original element, it's not a clone or anything. So the way you're hooking up the listener seems like it should work.

You might see if your changes to the filter trigger the onpropertychange event which is already hooked up. My understanding is that any change to a property of element.style, which includes filter, should trigger that. If that's the case then you should probably use that to avoid the cost of the extra event listener.

Author:  mario [ Thu Feb 10, 2011 2:08 pm ]
Post subject:  Re: Extending CSS3 Pie

Hey Jason,

thanks for your hint, but onpropertychange isn't fired when the style.filter attribute is changed.
After lots of testing I found out, that when attaching onfilterchange via addListener/attachEvent it is fired only sometimes. I have to restart or reload IE (6, 7 and 8) about 20 times until it's fired for the current session. Very weird! However, it seems like if I attach an event using tags, it behaves completely normal. It's fired, when it's changed:
<PUBLIC:ATTACH EVENT="onfilterchange" FOR="element" ONEVENT="alert(element.style.filter)" />

It's the first time, I'm playing around with htc files, so I feel a bit lost. But I won't give up ;-)
I'll keep you updated if I make any progress.


Author:  mario [ Sat Feb 12, 2011 6:50 am ]
Post subject:  Re: Extending CSS3 Pie

Hey there,

I made some progress - at least now the browser triggers an onfilterchange event. However, as onfilterchange is called very often for animations, I wanted to check the current renderers alpha value before I redraw everything. I've added a method in e.g. BackgroundRenderer, which is called to determine whether the element's filter is different to the renderers current alpha value. However, if I call this.styleInfos.backgroundInfo.getProps() to get the props and color attribute within that method, the renderer breaks.

In the event listener I just call the Renderer's needsFilterUpdate and updateFilter method:
3400                     for( i = 0, len = renderers.length; i < len; i++ ) {
3401                         renderer = renderers[i];
3402                         if( renderer.needsFilterUpdate() ) {
3403                             renderer.updateFilter();
3404                         }
3405                     }

BaseRenderer contains a dummy needsFilterUpdate, which returns false. BackgroundRenderer checks for the alpha value:
1754      needsFilterUpdate: function() {
1755         var props = this.styleInfos.backgroundInfo.getProps(),
1756             el = this.targetElement,
1757             color = props && props.color,
1758             alpha = color.alpha();
1759         return (((/opacity=([0-9]+)/i.exec(el.style.filter))[1] || 100)/100 != alpha);
1760     },

But as soon as I call this.styleInfos.backgroundInfo.getProps() outside of draw(), the draw method doesn't render any child anymore. It doesn't display anny error messages.
I guess getProps isn't supposed to be executed outside of draw(). But how do I determine the current Renderer's alpha value then? I rather don't want to add attributes, that get updated every time draw() is executed (which would be a solution - but an ugly one).

So, how to get the Renderer's alpha value without breaking draw()?


Page 1 of 1 All times are UTC - 7 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group