Permalink
Browse files

IE9: Allow border-image and -pie-background:linear-gradient to work t…

…ogether by delegating management of the runtimeStyle background to the root renderer. Allow linear-gradient to handle background-size properly. Prevent border-image renderer's destroy method from clobbering border hiding in IE<9.
  • Loading branch information...
1 parent c5ecdd7 commit f745eac9a2de287afb793c0d37f07ba6c65cf804 Jason Johnston committed Aug 8, 2011
View
@@ -44,6 +44,7 @@
<fileset file="${src_dir}/BoxShadowOutsetRenderer.js" />
<!--<fileset file="${src_dir}/BoxShadowInsetRenderer.js" />-->
<fileset file="${src_dir}/ImgRenderer.js" />
+ <fileset file="${src_dir}/IE9RootRenderer.js" />
<fileset file="${src_dir}/IE9BackgroundRenderer.js" />
<fileset file="${src_dir}/IE9BorderImageRenderer.js" />
<fileset file="${src_dir}/Element.js" />
@@ -13,6 +13,15 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
originAndClipIdents: { 'padding-box':1, 'border-box':1, 'content-box':1 },
positionIdents: { 'top':1, 'right':1, 'bottom':1, 'left':1, 'center':1 },
sizeIdents: { 'contain':1, 'cover':1 },
+ propertyNames: {
+ CLIP: 'backgroundClip',
+ COLOR: 'backgroundColor',
+ IMAGE: 'backgroundImage',
+ ORIGIN: 'backgroundOrigin',
+ POSITION: 'backgroundPosition',
+ REPEAT: 'backgroundRepeat',
+ SIZE: 'backgroundSize'
+ },
/**
* For background styles, we support the -pie-background property but fall back to the standard
@@ -62,7 +71,7 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
beginCharIndex = 0,
positionIdents = this.positionIdents,
gradient, stop, width, height,
- props = null;
+ props = { bgImages: [] };
function isBgPosToken( token ) {
return token && token.isLengthOrPercent() || ( token.tokenType & type_ident && token.tokenValue in positionIdents );
@@ -75,7 +84,6 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
// If the CSS3-specific -pie-background property is present, parse it
if( this.getCss3() ) {
tokenizer = new PIE.Tokenizer( css );
- props = { bgImages: [] };
image = {};
while( token = tokenizer.next() ) {
@@ -215,34 +223,76 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
// leftovers
if( image.imgType ) {
+ image.origString = css.substring( beginCharIndex );
props.bgImages.push( image );
}
}
// Otherwise, use the standard background properties; let IE give us the values rather than parsing them
else {
- this.withActualBg( function() {
- var posX = cs.backgroundPositionX,
- posY = cs.backgroundPositionY,
- img = cs.backgroundImage,
- color = cs.backgroundColor;
+ this.withActualBg( PIE.ieDocMode < 9 ?
+ function() {
+ var propNames = this.propertyNames,
+ posX = cs[propNames.POSITION + 'X'],
+ posY = cs[propNames.POSITION + 'Y'],
+ img = cs[propNames.IMAGE],
+ color = cs[propNames.COLOR];
- props = {};
- if( color !== 'transparent' ) {
- props.color = PIE.getColor( color )
- }
- if( img !== 'none' ) {
- props.bgImages = [ {
- imgType: 'image',
- imgUrl: new PIE.Tokenizer( img ).next().tokenValue,
- imgRepeat: cs.backgroundRepeat,
- bgPosition: new PIE.BgPosition( new PIE.Tokenizer( posX + ' ' + posY ).all() )
- } ];
+ if( color !== 'transparent' ) {
+ props.color = PIE.getColor( color )
+ }
+ if( img !== 'none' ) {
+ props.bgImages = [ {
+ imgType: 'image',
+ imgUrl: new PIE.Tokenizer( img ).next().tokenValue,
+ imgRepeat: cs[propNames.REPEAT],
+ bgPosition: new PIE.BgPosition( new PIE.Tokenizer( posX + ' ' + posY ).all() )
+ } ];
+ }
+ } :
+ function() {
+ var propNames = this.propertyNames,
+ splitter = /\s*,\s*/,
+ images = cs[propNames.IMAGE].split( splitter ),
+ color = cs[propNames.COLOR],
+ repeats, positions, origins, clips, sizes, i, len, image, sizeParts;
+
+ if( color !== 'transparent' ) {
+ props.color = PIE.getColor( color )
+ }
+
+ len = images.length;
+ if( len && images[0] !== 'none' ) {
+ repeats = cs[propNames.REPEAT].split( splitter );
+ positions = cs[propNames.POSITION].split( splitter );
+ origins = cs[propNames.ORIGIN].split( splitter );
+ clips = cs[propNames.CLIP].split( splitter );
+ sizes = cs[propNames.SIZE].split( splitter );
+
+ props.bgImages = [];
+ for( i = 0; i < len; i++ ) {
+ image = images[ i ];
+ if( image && image !== 'none' ) {
+ sizeParts = sizes[i].split( ' ' );
+ props.bgImages.push( {
+ origString: image + ' ' + repeats[ i ] + ' ' + positions[ i ] + ' / ' + sizes[ i ] + ' ' +
+ origins[ i ] + ' ' + clips[ i ],
+ imgType: 'image',
+ imgUrl: new PIE.Tokenizer( image ).next().tokenValue,
+ imgRepeat: repeats[ i ],
+ bgPosition: new PIE.BgPosition( new PIE.Tokenizer( positions[ i ] ).all() ),
+ bgOrigin: origins[ i ],
+ bgClip: clips[ i ],
+ bgSize: new PIE.BgSize( sizeParts[ 0 ], sizeParts[ 1 ] )
+ } );
+ }
+ }
+ }
}
- } );
+ );
}
- return ( props && ( props.color || ( props.bgImages && props.bgImages[0] ) ) ) ? props : null;
+ return ( props.color || props.bgImages[0] ) ? props : null;
},
/**
@@ -251,28 +301,50 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
* @param fn
*/
withActualBg: function( fn ) {
- var rs = this.targetElement.runtimeStyle,
- rsImage = rs.backgroundImage,
- rsColor = rs.backgroundColor,
- ret;
+ var isIE9 = PIE.ieDocMode > 8,
+ propNames = this.propertyNames,
+ rs = this.targetElement.runtimeStyle,
+ rsImage = rs[propNames.IMAGE],
+ rsColor = rs[propNames.COLOR],
+ rsRepeat = rs[propNames.REPEAT],
+ rsClip, rsOrigin, rsSize, rsPosition, ret;
- if( rsImage ) rs.backgroundImage = '';
- if( rsColor ) rs.backgroundColor = '';
+ if( rsImage ) rs[propNames.IMAGE] = '';
+ if( rsColor ) rs[propNames.COLOR] = '';
+ if( rsRepeat ) rs[propNames.REPEAT] = '';
+ if( isIE9 ) {
+ rsClip = rs[propNames.CLIP];
+ rsOrigin = rs[propNames.ORIGIN];
+ rsPosition = rs[propNames.POSITION];
+ rsSize = rs[propNames.SIZE];
+ if( rsClip ) rs[propNames.CLIP] = '';
+ if( rsOrigin ) rs[propNames.ORIGIN] = '';
+ if( rsPosition ) rs[propNames.POSITION] = '';
+ if( rsSize ) rs[propNames.SIZE] = '';
+ }
ret = fn.call( this );
- if( rsImage ) rs.backgroundImage = rsImage;
- if( rsColor ) rs.backgroundColor = rsColor;
+ if( rsImage ) rs[propNames.IMAGE] = rsImage;
+ if( rsColor ) rs[propNames.COLOR] = rsColor;
+ if( rsRepeat ) rs[propNames.REPEAT] = rsRepeat;
+ if( isIE9 ) {
+ if( rsClip ) rs[propNames.CLIP] = rsClip;
+ if( rsOrigin ) rs[propNames.ORIGIN] = rsOrigin;
+ if( rsPosition ) rs[propNames.POSITION] = rsPosition;
+ if( rsSize ) rs[propNames.SIZE] = rsSize;
+ }
return ret;
},
getCss: PIE.StyleInfoBase.cacheWhenLocked( function() {
return this.getCss3() ||
this.withActualBg( function() {
- var cs = this.targetElement.currentStyle;
- return cs.backgroundColor + ' ' + cs.backgroundImage + ' ' + cs.backgroundRepeat + ' ' +
- cs.backgroundPositionX + ' ' + cs.backgroundPositionY;
+ var cs = this.targetElement.currentStyle,
+ propNames = this.propertyNames;
+ return cs[propNames.COLOR] + ' ' + cs[propNames.IMAGE] + ' ' + cs[propNames.REPEAT] + ' ' +
+ cs[propNames.POSITION + 'X'] + ' ' + cs[propNames.POSITION + 'Y'];
} );
} ),
@@ -145,8 +145,10 @@ PIE.BorderImageRenderer = PIE.RendererBase.newRenderer( {
},
destroy: function() {
- var rs = this.targetElement.runtimeStyle;
- rs.borderColor = rs.borderStyle = rs.borderWidth = '';
+ if (!this.finalized && !this.styleInfos.borderInfo.isActive()) {
+ var rs = this.targetElement.runtimeStyle;
+ rs.borderColor = rs.borderStyle = rs.borderWidth = '';
+ }
}
} );
@@ -26,9 +26,9 @@ PIE.BorderRenderer = PIE.RendererBase.newRenderer( {
isActive: function() {
var si = this.styleInfos;
- return ( si.borderImageInfo.isActive() ||
- si.borderRadiusInfo.isActive() ||
+ return ( si.borderRadiusInfo.isActive() ||
si.backgroundInfo.isActive() ) &&
+ !si.borderImageInfo.isActive() &&
si.borderInfo.isActive(); //check BorderStyleInfo last because it's the most expensive
},
@@ -37,12 +37,11 @@ PIE.BorderRenderer = PIE.RendererBase.newRenderer( {
*/
draw: function() {
var el = this.targetElement,
- cs = el.currentStyle,
props = this.styleInfos.borderInfo.getProps(),
bounds = this.boundsInfo.getBounds(),
w = bounds.w,
h = bounds.h,
- side, shape, stroke, s,
+ shape, stroke, s,
segments, seg, i, len;
if( props ) {
@@ -307,7 +306,9 @@ PIE.BorderRenderer = PIE.RendererBase.newRenderer( {
destroy: function() {
PIE.RendererBase.destroy.call( this );
- this.targetElement.runtimeStyle.borderColor = '';
+ if (!this.finalized && !this.styleInfos.borderImageInfo.isActive()) {
+ this.targetElement.runtimeStyle.borderColor = '';
+ }
}
View
@@ -20,6 +20,7 @@ PIE.Element = (function() {
function Element( el ) {
var renderers,
+ rootRenderer,
boundsInfo = new PIE.BoundsInfo( el ),
styleInfos,
styleInfosArr,
@@ -41,7 +42,7 @@ PIE.Element = (function() {
ieDocMode = PIE.ieDocMode,
cs = el.currentStyle,
lazy = cs.getAttribute( lazyInitCssProp ) === 'true',
- rootRenderer, childRenderers;
+ childRenderers;
// Polling for size/position changes: default to on in IE8, off otherwise, overridable by -pie-poll
poll = cs.getAttribute( pollCssProp );
@@ -73,15 +74,17 @@ PIE.Element = (function() {
if ( ieDocMode === 9 ) {
styleInfos = {
backgroundInfo: new PIE.BackgroundStyleInfo( el ),
- borderImageInfo: new PIE.BorderImageStyleInfo( el )
+ borderImageInfo: new PIE.BorderImageStyleInfo( el ),
+ borderInfo: new PIE.BorderStyleInfo( el )
};
styleInfosArr = [
styleInfos.backgroundInfo,
styleInfos.borderImageInfo
];
- renderers = [
- new PIE.IE9BackgroundRenderer( el, boundsInfo, styleInfos ),
- new PIE.IE9BorderImageRenderer( el, boundsInfo, styleInfos )
+ rootRenderer = new PIE.IE9RootRenderer( el, boundsInfo, styleInfos );
+ childRenderers = [
+ new PIE.IE9BackgroundRenderer( el, boundsInfo, styleInfos, rootRenderer ),
+ new PIE.IE9BorderImageRenderer( el, boundsInfo, styleInfos, rootRenderer )
];
} else {
@@ -101,7 +104,6 @@ PIE.Element = (function() {
styleInfos.boxShadowInfo,
styleInfos.visibilityInfo
];
-
rootRenderer = new PIE.RootRenderer( el, boundsInfo, styleInfos );
childRenderers = [
new PIE.BoxShadowOutsetRenderer( el, boundsInfo, styleInfos, rootRenderer ),
@@ -114,8 +116,8 @@ PIE.Element = (function() {
childRenderers.push( new PIE.ImgRenderer( el, boundsInfo, styleInfos, rootRenderer ) );
}
rootRenderer.childRenderers = childRenderers; // circular reference, can't pass in constructor; TODO is there a cleaner way?
- renderers = [ rootRenderer ].concat( childRenderers );
}
+ renderers = [ rootRenderer ].concat( childRenderers );
// Add property change listeners to ancestors if requested
initAncestorPropChangeListeners();
@@ -194,6 +196,7 @@ PIE.Element = (function() {
renderers[i].updateSize();
}
}
+ rootRenderer.finishUpdate();
unlockAll();
}
else if( !initializing ) {
@@ -232,6 +235,7 @@ PIE.Element = (function() {
renderer.updateProps();
}
}
+ rootRenderer.finishUpdate();
unlockAll();
}
else if( !initializing ) {
@@ -339,6 +343,7 @@ PIE.Element = (function() {
// destroy any active renderers
if( renderers ) {
for( i = 0, len = renderers.length; i < len; i++ ) {
+ renderers[i].finalized = 1;
renderers[i].destroy();
}
}
Oops, something went wrong.

0 comments on commit f745eac

Please sign in to comment.