Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

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.
base fork: lojjic/PIE
...
head fork: lojjic/PIE
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.