Skip to content
Browse files

Add support for text-shadow on nested mixed markup. Handle text-inden…

…t and inline elements that don't start at the beginning of the line.
  • Loading branch information...
1 parent 7f4922c commit cf7f20784ac8206b9513890667a932aa6745f2e5 Jason Johnston committed Jun 19, 2011
Showing with 106 additions and 13 deletions.
  1. +73 −13 sources/TextShadowRenderer.js
  2. +33 −0 tests/text-shadow-tests.html
View
86 sources/TextShadowRenderer.js
@@ -20,6 +20,15 @@ PIE.TextShadowRenderer = PIE.RendererBase.newRenderer( {
return textShadowInfo.isActive() && textShadowInfo.getProps();
},
+ copyTextStyles: function( from, to ) {
+ var fromStyle = from.currentStyle,
+ toStyle = to.style,
+ textStyles = this.textStyles,
+ i = textStyles.length;
+ while( i-- ) {
+ toStyle[ textStyles[ i ] ] = fromStyle[ textStyles[ i ] ];
+ }
+ },
draw: function() {
var el = this.targetElement,
@@ -28,17 +37,25 @@ PIE.TextShadowRenderer = PIE.RendererBase.newRenderer( {
si = this.styleInfos,
shadowProps = si.textShadowInfo.getProps(),
i = shadowProps.length,
- textStyles = this.textStyles,
getLength = PIE.getLength,
bounds = this.boundsInfo.getBounds(),
borderProps = si.borderInfo.getProps(),
borderWidths = borderProps && borderProps.widths,
borderTopWidth = borderWidths ? borderWidths['t'].pixels( el ) : 0,
borderLeftWidth = borderWidths ? borderWidths['l'].pixels( el ) : 0,
+ borderRightWidth = borderWidths ? borderWidths['r'].pixels( el ) : 0,
+ paddingLeft = getLength( currentStyle.paddingLeft ).pixels( el ),
+ paddingRight = getLength( currentStyle.paddingRight ).pixels( el ),
+ paddingTop = getLength( currentStyle.paddingTop ).pixels( el ),
+ indent = currentStyle.display === 'block' ?
+ getLength( currentStyle.textIndent ).pixels( el ) :
+ currentStyle.display === 'inline' ? el.getClientRects()[0].left - bounds.x : 0,
filterPrefix = 'progid:DXImageTransform.Microsoft.',
math = Math,
round = math.round,
- props, shadowEl, shadowStyle, color, blur, blurLog, glow, opacity, j;
+ childNodes = el.childNodes,
+ childCount = childNodes.length,
+ props, shadowEl, shadowStyle, color, blur, blurLog, glow, opacity, j, child, clone;
box.innerHTML = '';
@@ -73,24 +90,67 @@ PIE.TextShadowRenderer = PIE.RendererBase.newRenderer( {
filterPrefix + 'Blur(PixelRadius=' + ( blur - glow ) + ',MakeShadow=false)';
}
+ // Size and position the shadow element
shadowStyle.position = 'absolute';
- shadowStyle.left = props.xOffset.pixels( el ) - round(blur) + borderLeftWidth +
- getLength( currentStyle.paddingLeft ).pixels( el );
- shadowStyle.top = props.yOffset.pixels( el ) - round(blur) + borderTopWidth +
- getLength( currentStyle.paddingTop ).pixels( el );
- shadowStyle.width = bounds.w;
- shadowStyle.height = bounds.h;
+ shadowStyle.left = props.xOffset.pixels( el ) - round(blur) + borderLeftWidth + paddingLeft;
+ shadowStyle.top = props.yOffset.pixels( el ) - round(blur) + borderTopWidth + paddingTop;
+ shadowStyle.width = bounds.w - paddingLeft - paddingRight - borderLeftWidth - borderRightWidth + round(blur) * 2;
+
+ // Handle indentation of the first line, either due to text-indent CSS on a block element
+ // or an inline element that is not the first text on the line and wraps to a second line.
+ shadowStyle.textIndent = indent;
// Copy the original text's styles to the shadow element
- j = textStyles.length;
- while( j-- ) {
- shadowStyle[ textStyles[ j ] ] = currentStyle[ textStyles[ j ] ];
- }
+ this.copyTextStyles( el, shadowEl );
shadowStyle.color = color.colorValue( el );
- shadowEl.innerText = el.innerText;
+
+ if ( el.tagName.toLowerCase() in { input:1, textarea:1 } ) {
+ shadowEl.innerText = el.value;
+ } else {
+ var childElements = [];
+ for( j = 0; j < childCount; j++ ) {
+ child = childNodes[ j ];
+ if ( child.nodeType === 1 && child.tagName.toLowerCase() !== 'css3-container' ) {
+ clone = this.deepCopy( child );
+ clone.style.visibility = 'hidden';
+ shadowEl.appendChild( clone );
+
+ clone.style.zoom = 1; //The original child is going to get layout by attaching PIE, so force layout on the clone to match
+ childElements.push( child );
+ }
+ else if ( child.nodeType === 3 ) {
+ shadowEl.appendChild( child.cloneNode() );
+ }
+ }
+
+ for( j = childElements.length; j--; ) {
+ PIE.attach( childElements[ j ] );
+ }
+ }
+
box.appendChild( shadowEl );
}
+ },
+
+ deepCopy: function( el ) {
+ var copy = doc.createElement( 'subel' ),
+ childNodes = el.childNodes,
+ childLength = childNodes.length,
+ i = 0, child, nodeType;
+ this.copyTextStyles( el, copy );
+ for ( ; i < childLength; i++ ) {
+ child = childNodes[ i ];
+ nodeType = child.nodeType;
+ if ( nodeType == 1 && child.tagName !== 'css3-container' ) {
+ copy.appendChild( this.deepCopy( child ) );
+ }
+ else if ( nodeType == 3 ) {
+ copy.appendChild( child.cloneNode() );
+ }
+ }
+ copy.style.display = el.currentStyle.display;
+ return copy;
}
} );
View
33 tests/text-shadow-tests.html
@@ -11,6 +11,10 @@
font-family: Arial;
}
+ * {
+ -pie-poll: false;
+ }
+
/* From http://www.w3.org/Style/Examples/007/text-shadow */
#w3c-tests div {
float: left;
@@ -34,6 +38,29 @@
/*#w3c12 {color: #fff; text-shadow: -2px -2px 2px #0000FF, 2px 2px 2px #FF0000, 0 -2px 2px #0000FF, 0 2px 2px #FF0000}*/
#w3c12 {text-shadow: 0 0 0.2em #87F, 0 0 0.2em #87F, 0 0 0.2em #87F}
+ #mixedMarkup {
+ behavior: url(../build/PIE_uncompressed.htc);
+ text-shadow: 1px 1px 2px #666;
+ clear: both;
+ width: 350px;
+ text-indent: 0.5em;
+ }
+ #mixedMarkup em {
+ text-shadow: 0 0 5px red;
+ }
+ #mixedMarkup .nested {
+ text-shadow: 0 -2px 4px blue;
+ }
+ #mixedMarkup .nested span {
+ text-shadow: 0 2px 2px green, 0 4px 2px yellow;
+ }
+ #mixedMarkup .multiline {
+ color: #FFF;
+ text-shadow: -1px 0 purple, 0 1px purple, 1px 0 purple, 0 -1px purple;
+ }
+ #mixedMarkup strong {
+ text-shadow: none;
+ }
.tester {
behavior: url(../build/PIE_uncompressed.htc);
@@ -60,6 +87,12 @@
<div id="w3c12">PIE</div>
</div>
+<div id="mixedMarkup">
+ This is an example of <em>mixed markup</em>.
+ It can be <span class="nested">deeply <span>nested</span> too</span> and can <span class="multiline">span across multiple lines</span>.
+ The shadow can also be <strong>removed entirely</strong> from nested nodes.
+</div>
+
<script type="text/javascript">
var n = 25;

0 comments on commit cf7f207

Please sign in to comment.
Something went wrong with that request. Please try again.