Skip to content

Commit

Permalink
IE9: Allow border-image and -pie-background:linear-gradient to work t…
Browse files Browse the repository at this point in the history
…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
Jason Johnston committed Aug 8, 2011
1 parent c5ecdd7 commit 22ae244
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 68 deletions.
1 change: 1 addition & 0 deletions build.xml
Expand Up @@ -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" />
Expand Down
135 changes: 104 additions & 31 deletions sources/BackgroundStyleInfo.js
Expand Up @@ -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
Expand Down Expand Up @@ -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 );
Expand All @@ -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() ) {
Expand Down Expand Up @@ -215,34 +223,77 @@ 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() )
} ];
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[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;
},

/**
Expand All @@ -251,28 +302,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';
} );
} ),

Expand Down
6 changes: 4 additions & 2 deletions sources/BorderImageRenderer.js
Expand Up @@ -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 = '';
}
}

} );
11 changes: 6 additions & 5 deletions sources/BorderRenderer.js
Expand Up @@ -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
},

Expand All @@ -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 ) {
Expand Down Expand Up @@ -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 = '';
}
}


Expand Down
19 changes: 12 additions & 7 deletions sources/Element.js
Expand Up @@ -20,6 +20,7 @@ PIE.Element = (function() {

function Element( el ) {
var renderers,
rootRenderer,
boundsInfo = new PIE.BoundsInfo( el ),
styleInfos,
styleInfosArr,
Expand All @@ -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 );
Expand Down Expand Up @@ -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 {

Expand All @@ -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 ),
Expand All @@ -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();
Expand Down Expand Up @@ -194,6 +196,7 @@ PIE.Element = (function() {
renderers[i].updateSize();
}
}
rootRenderer.finishUpdate();
unlockAll();
}
else if( !initializing ) {
Expand Down Expand Up @@ -232,6 +235,7 @@ PIE.Element = (function() {
renderer.updateProps();
}
}
rootRenderer.finishUpdate();
unlockAll();
}
else if( !initializing ) {
Expand Down Expand Up @@ -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();
}
}
Expand Down

0 comments on commit 22ae244

Please sign in to comment.