Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 9 files changed
  • 0 commit comments
  • 1 contributor
Commits on Aug 08, 2011
Jason Johnston 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.
22ae244
View
1 build.xml
@@ -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" />
View
135 sources/BackgroundStyleInfo.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,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;
},
/**
@@ -251,18 +302,39 @@ 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;
},
@@ -270,9 +342,10 @@ PIE.BackgroundStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
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';
} );
} ),
View
6 sources/BorderImageRenderer.js
@@ -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 = '';
+ }
}
} );
View
11 sources/BorderRenderer.js
@@ -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
19 sources/Element.js
@@ -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();
}
}
View
73 sources/IE9BackgroundRenderer.js
@@ -7,6 +7,8 @@
*/
PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
+ bgLayerZIndex: 1,
+
needsUpdate: function() {
var si = this.styleInfos;
return si.backgroundInfo.changed();
@@ -14,12 +16,13 @@ PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
isActive: function() {
var si = this.styleInfos;
- return si.backgroundInfo.isActive();
+ return si.backgroundInfo.isActive() || si.borderImageInfo.isActive();
},
draw: function() {
- var props = this.styleInfos.backgroundInfo.getProps(),
- bg, images, i = 0, img;
+ var me = this,
+ props = me.styleInfos.backgroundInfo.getProps(),
+ bg, images, i = 0, img, bgAreaSize, bgSize;
if ( props ) {
bg = [];
@@ -27,11 +30,19 @@ PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
images = props.bgImages;
if ( images ) {
while( img = images[ i++ ] ) {
- bg.push( img.imgType === 'linear-gradient' ?
- 'url(data:image/svg+xml,' + escape( this.getGradientSvg( img ) ) + ') ' +
- ( img.imgRepeat || '' ) + ' ' + this.bgPositionToString( img.bgPosition ) :
- img.origString
- );
+ if (img.imgType === 'linear-gradient' ) {
+ bgAreaSize = me.getBgAreaSize( img.bgOrigin );
+ bgSize = ( img.bgSize || PIE.BgSize.DEFAULT ).pixels(
+ me.targetElement, bgAreaSize.w, bgAreaSize.h, bgAreaSize.w, bgAreaSize.h
+ ),
+ bg.push(
+ 'url(data:image/svg+xml,' + escape( me.getGradientSvg( img, bgSize.w, bgSize.h ) ) + ') ' +
+ me.bgPositionToString( img.bgPosition ) + ' / ' + bgSize.w + 'px ' + bgSize.h + 'px ' +
+ ( img.bgAttachment || '' ) + ' ' + ( img.bgOrigin || '' ) + ' ' + ( img.bgClip || '' )
+ );
+ } else {
+ bg.push( img.origString );
+ }
}
}
@@ -39,25 +50,49 @@ PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
bg.push( props.color.val );
}
- this.targetElement.runtimeStyle.background = bg.join(', ');
+ me.parent.setBackgroundLayer(me.bgLayerZIndex, bg.join(','));
}
},
bgPositionToString: function( bgPosition ) {
return bgPosition ? bgPosition.tokens.map(function(token) {
return token.tokenValue;
- }).join(' ') : '';
+ }).join(' ') : '0 0';
+ },
+
+ getBgAreaSize: function( bgOrigin ) {
+ var me = this,
+ el = me.targetElement,
+ bounds = me.boundsInfo.getBounds(),
+ elW = bounds.w,
+ elH = bounds.h,
+ w = elW,
+ h = elH,
+ borders, getLength, cs;
+
+ if( bgOrigin !== 'border-box' ) {
+ borders = me.styleInfos.borderInfo.getProps();
+ if( borders && ( borders = borders.widths ) ) {
+ w -= borders[ 'l' ].pixels( el ) + borders[ 'l' ].pixels( el );
+ h -= borders[ 't' ].pixels( el ) + borders[ 'b' ].pixels( el );
+ }
+ }
+
+ if ( bgOrigin === 'content-box' ) {
+ getLength = PIE.getLength;
+ cs = el.currentStyle;
+ w -= getLength( cs.paddingLeft ).pixels( el ) + getLength( cs.paddingRight ).pixels( el );
+ h -= getLength( cs.paddingTop ).pixels( el ) + getLength( cs.paddingBottom ).pixels( el );
+ }
+
+ return { w: w, h: h };
},
- getGradientSvg: function( info ) {
+ getGradientSvg: function( info, bgWidth, bgHeight ) {
var el = this.targetElement,
- bounds = this.boundsInfo.getBounds(),
stopsInfo = info.stops,
stopCount = stopsInfo.length,
- bgSize = ( info.bgSize || PIE.BgSize.DEFAULT ).pixels( el, bounds.w, bounds.h, bounds.w, bounds.h ),
- w = bgSize.w,
- h = bgSize.h,
- metrics = PIE.GradientUtil.getGradientMetrics( el, w, h, info ),
+ metrics = PIE.GradientUtil.getGradientMetrics( el, bgWidth, bgHeight, info ),
startX = metrics.startX,
startY = metrics.startY,
endX = metrics.endX,
@@ -86,10 +121,10 @@ PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
}
svg = [
- '<svg width="' + w + '" height="' + h + '" xmlns="http://www.w3.org/2000/svg">' +
+ '<svg width="' + bgWidth + '" height="' + bgHeight + '" xmlns="http://www.w3.org/2000/svg">' +
'<defs>' +
'<linearGradient id="g" gradientUnits="userSpaceOnUse"' +
- ' x1="' + ( startX / w * 100 ) + '%" y1="' + ( startY / h * 100 ) + '%" x2="' + ( endX / w * 100 ) + '%" y2="' + ( endY / h * 100 ) + '%">'
+ ' x1="' + ( startX / bgWidth * 100 ) + '%" y1="' + ( startY / bgHeight * 100 ) + '%" x2="' + ( endX / bgWidth * 100 ) + '%" y2="' + ( endY / bgHeight * 100 ) + '%">'
];
// Convert to percentage along the SVG gradient line and add to the stops list
@@ -112,7 +147,7 @@ PIE.IE9BackgroundRenderer = PIE.RendererBase.newRenderer( {
},
destroy: function() {
-// this.targetElement.runtimeStyle.background = '';
+ this.parent.setBackgroundLayer( this.bgLayerZIndex );
}
} );
View
21 sources/IE9BorderImageRenderer.js
@@ -11,6 +11,8 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
STRETCH: 'stretch',
ROUND: 'round',
+ bgLayerZIndex: 0,
+
needsUpdate: function() {
return this.styleInfos.borderImageInfo.changed();
},
@@ -28,7 +30,7 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
repeatV = repeat.v,
el = me.targetElement,
cs = el.currentStyle,
- rs = el.runtimeStyle;
+ isAsync = 0;
PIE.Util.withImageSize( props.src, function( imgSize ) {
var elW = bounds.w,
@@ -129,8 +131,17 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
'</svg>'
);
- rs.background = 'url(data:image/svg+xml,' + escape( svg.join( '' ) ) + ') no-repeat border-box border-box';
+ me.parent.setBackgroundLayer( me.bgLayerZIndex, 'url(data:image/svg+xml,' + escape( svg.join( '' ) ) + ') no-repeat border-box border-box' );
+
+ // If the border-image's src wasn't immediately available, the SVG for its background layer
+ // will have been created asynchronously after the main element's update has finished; we'll
+ // therefore need to force the root renderer to sync to the final background once finished.
+ if( isAsync ) {
+ me.parent.finishUpdate();
+ }
}, me );
+
+ isAsync = 1;
},
/**
@@ -157,8 +168,10 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
prepareUpdate: PIE.BorderImageRenderer.prototype.prepareUpdate,
destroy: function() {
- var rs = this.targetElement.runtimeStyle;
- rs.background = rs.borderColor = rs.borderStyle = rs.borderWidth = '';
+ var me = this,
+ rs = me.targetElement.runtimeStyle;
+ me.parent.setBackgroundLayer( me.bgLayerZIndex );
+ rs.borderColor = rs.borderStyle = rs.borderWidth = '';
}
} );
View
37 sources/IE9RootRenderer.js
@@ -0,0 +1,37 @@
+/**
+ * Root renderer for IE9; manages the rendering layers in the element's background
+ * @param {Element} el The target element
+ * @param {Object} styleInfos The StyleInfo objects
+ */
+PIE.IE9RootRenderer = PIE.RendererBase.newRenderer( {
+
+ updatePos: PIE.emptyFn,
+ updateSize: PIE.emptyFn,
+ updateVisibility: PIE.emptyFn,
+ updateProps: PIE.emptyFn,
+
+ outerCommasRE: /^,+|,+$/g,
+ innerCommasRE: /,+/g,
+
+ setBackgroundLayer: function(zIndex, bg) {
+ var me = this,
+ bgLayers = me._bgLayers || ( me._bgLayers = [] ),
+ undef;
+ bgLayers[zIndex] = bg || undef;
+ },
+
+ finishUpdate: function() {
+ var me = this,
+ bgLayers = me._bgLayers,
+ bg;
+ if( bgLayers && ( bg = bgLayers.join( ',' ).replace( me.outerCommasRE, '' ).replace( me.innerCommasRE, ',' ) ) !== me._lastBg ) {
+ me._lastBg = me.targetElement.runtimeStyle.background = bg;
+ }
+ },
+
+ destroy: function() {
+ this.targetElement.runtimeStyle.background = '';
+ delete this._bgLayers;
+ }
+
+} );
View
1 sources/StyleInfoBase.js
@@ -25,6 +25,7 @@ PIE.StyleInfoBase = {
newStyleInfo: function( proto ) {
function StyleInfo( el ) {
this.targetElement = el;
+ this._lastCss = this.getCss();
}
PIE.Util.merge( StyleInfo.prototype, PIE.StyleInfoBase, proto );
StyleInfo._propsCache = {};

No commit comments for this range

Something went wrong with that request. Please try again.