Permalink
Browse files

Allow border-image renderer to properly hide border on button/input e…

…lements.
  • Loading branch information...
1 parent ded481a commit e270f7b84bdc0b126c730f45540664659cf40cea Jason Johnston committed Sep 4, 2011
@@ -22,26 +22,25 @@ PIE.BorderImageRenderer = PIE.RendererBase.newRenderer( {
this.getBox(); //make sure pieces are created
var props = this.styleInfos.borderImageInfo.getProps(),
+ borderProps = this.styleInfos.borderInfo.getProps(),
bounds = this.boundsInfo.getBounds(),
el = this.targetElement,
pieces = this.pieces;
PIE.Util.withImageSize( props.src, function( imgSize ) {
var elW = bounds.w,
elH = bounds.h,
- getLength = PIE.getLength,
- cs = el.currentStyle,
-
- widths = props.width,
- widthT = ( widths ? widths.t : getLength( cs.borderTopWidth ) ).pixels( el ),
- widthR = ( widths ? widths.r : getLength( cs.borderRightWidth ) ).pixels( el ),
- widthB = ( widths ? widths.b : getLength( cs.borderBottomWidth ) ).pixels( el ),
- widthL = ( widths ? widths.l : getLength( cs.borderLeftWidth ) ).pixels( el ),
+ zero = PIE.getLength( '0' ),
+ widths = props.widths || ( borderProps ? borderProps.widths : { 't': zero, 'r': zero, 'b': zero, 'l': zero } ),
+ widthT = widths['t'].pixels( el ),
+ widthR = widths['r'].pixels( el ),
+ widthB = widths['b'].pixels( el ),
+ widthL = widths['l'].pixels( el ),
slices = props.slice,
- sliceT = slices.t.pixels( el ),
- sliceR = slices.r.pixels( el ),
- sliceB = slices.b.pixels( el ),
- sliceL = slices.l.pixels( el );
+ sliceT = slices['t'].pixels( el ),
+ sliceR = slices['r'].pixels( el ),
+ sliceB = slices['b'].pixels( el ),
+ sliceL = slices['l'].pixels( el );
// Piece positions and sizes
function setSizeAndPos( piece, w, h, x, y ) {
@@ -127,30 +126,33 @@ PIE.BorderImageRenderer = PIE.RendererBase.newRenderer( {
prepareUpdate: function() {
if (this.isActive()) {
var me = this,
- rs = me.targetElement.runtimeStyle,
el = me.targetElement,
- widths = me.styleInfos.borderImageInfo.getProps().width;
+ rs = el.runtimeStyle,
+ widths = me.styleInfos.borderImageInfo.getProps().widths;
- // Force border to solid transparent
- rs.borderColor = 'transparent';
+ // Force border-style to solid so it doesn't collapse
rs.borderStyle = 'solid';
// If widths specified in border-image shorthand, override border-width
+ // NOTE px units needed here as this gets used by the IE9 renderer too
if ( widths ) {
- rs.borderTopWidth = widths.t.pixels( el ) + 'px';
- rs.borderRightWidth = widths.r.pixels( el ) + 'px';
- rs.borderBottomWidth = widths.b.pixels( el ) + 'px';
- rs.borderLeftWidth = widths.l.pixels( el ) + 'px';
+ rs.borderTopWidth = widths['t'].pixels( el ) + 'px';
+ rs.borderRightWidth = widths['r'].pixels( el ) + 'px';
+ rs.borderBottomWidth = widths['b'].pixels( el ) + 'px';
+ rs.borderLeftWidth = widths['l'].pixels( el ) + 'px';
}
+
+ // Make the border transparent
+ me.hideBorder();
}
},
destroy: function() {
var me = this,
rs = me.targetElement.runtimeStyle;
- rs.borderStyle = rs.borderWidth = '';
+ rs.borderStyle = '';
if (me.finalized || !me.styleInfos.borderInfo.isActive()) {
- rs.borderColor = '';
+ rs.borderColor = rs.borderWidth = '';
}
PIE.RendererBase.destroy.call( this );
}
@@ -113,10 +113,10 @@ PIE.BorderImageStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
function distributeSides( tokens, convertFn ) {
return {
- t: convertFn( tokens[0] ),
- r: convertFn( tokens[1] || tokens[0] ),
- b: convertFn( tokens[2] || tokens[0] ),
- l: convertFn( tokens[3] || tokens[1] || tokens[0] )
+ 't': convertFn( tokens[0] ),
+ 'r': convertFn( tokens[1] || tokens[0] ),
+ 'b': convertFn( tokens[2] || tokens[0] ),
+ 'l': convertFn( tokens[3] || tokens[1] || tokens[0] )
};
}
@@ -125,7 +125,7 @@ PIE.BorderImageStyleInfo = PIE.StyleInfoBase.newStyleInfo( {
} );
if( widths && widths[0] ) {
- p.width = distributeSides( widths, function( tok ) {
+ p.widths = distributeSides( widths, function( tok ) {
return tok.isLengthOrPercent() ? PIE.getLength( tok.tokenValue ) : tok.tokenValue;
} );
}
View
@@ -10,15 +10,6 @@ PIE.BorderRenderer = PIE.RendererBase.newRenderer( {
boxZIndex: 4,
boxName: 'border',
- /**
- * Values of the type attribute for input elements displayed as buttons
- */
- inputButtonTypes: {
- 'submit':1,
- 'button':1,
- 'reset':1
- },
-
needsUpdate: function() {
var si = this.styleInfos;
return si.borderInfo.changed() || si.borderRadiusInfo.changed();
@@ -76,58 +67,6 @@ PIE.BorderRenderer = PIE.RendererBase.newRenderer( {
}
},
- /**
- * Hide the actual border of the element. In IE7 and up we can just set its color to transparent;
- * however IE6 does not support transparent borders so we have to get tricky with it. Also, some elements
- * like form buttons require removing the border width altogether, so for those we increase the padding
- * by the border size.
- */
- hideBorder: function() {
- var el = this.targetElement,
- cs = el.currentStyle,
- rs = el.runtimeStyle,
- tag = el.tagName,
- isIE6 = PIE.ieVersion === 6,
- sides, side, i;
-
- if( ( isIE6 && ( tag in PIE.childlessElements || tag === 'FIELDSET' ) ) ||
- tag === 'BUTTON' || ( tag === 'INPUT' && el.type in this.inputButtonTypes ) ) {
- rs.borderWidth = '';
- sides = this.styleInfos.borderInfo.sides;
- for( i = sides.length; i--; ) {
- side = sides[ i ];
- rs[ 'padding' + side ] = '';
- rs[ 'padding' + side ] = ( PIE.getLength( cs[ 'padding' + side ] ) ).pixels( el ) +
- ( PIE.getLength( cs[ 'border' + side + 'Width' ] ) ).pixels( el ) +
- ( !PIE.ieVersion === 8 && i % 2 ? 1 : 0 ); //needs an extra horizontal pixel to counteract the extra "inner border" going away
- }
- rs.borderWidth = 0;
- }
- else if( isIE6 ) {
- // Wrap all the element's children in a custom element, set the element to visiblity:hidden,
- // and set the wrapper element to visiblity:visible. This hides the outer element's decorations
- // (background and border) but displays all the contents.
- // TODO find a better way to do this that doesn't mess up the DOM parent-child relationship,
- // as this can interfere with other author scripts which add/modify/delete children. Also, this
- // won't work for elements which cannot take children, e.g. input/button/textarea/img/etc. Look into
- // using a compositor filter or some other filter which masks the border.
- if( el.childNodes.length !== 1 || el.firstChild.tagName !== 'ie6-mask' ) {
- var cont = doc.createElement( 'ie6-mask' ),
- s = cont.style, child;
- s.visibility = 'visible';
- s.zoom = 1;
- while( child = el.firstChild ) {
- cont.appendChild( child );
- }
- el.appendChild( cont );
- rs.visibility = 'hidden';
- }
- }
- else {
- rs.borderColor = 'transparent';
- }
- },
-
/**
* Get the VML path definitions for the border segment(s).
@@ -24,20 +24,19 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
draw: function() {
var me = this,
props = me.styleInfos.borderImageInfo.getProps(),
+ borderProps = me.styleInfos.borderInfo.getProps(),
bounds = me.boundsInfo.getBounds(),
repeat = props.repeat,
repeatH = repeat.h,
repeatV = repeat.v,
el = me.targetElement,
- cs = el.currentStyle,
isAsync = 0;
PIE.Util.withImageSize( props.src, function( imgSize ) {
var elW = bounds.w,
elH = bounds.h,
imgW = imgSize.w,
imgH = imgSize.h,
- getLength = PIE.getLength,
// The image cannot be referenced as a URL directly in the SVG because IE9 throws a strange
// security exception (perhaps due to cross-origin policy within data URIs?) Therefore we
@@ -51,16 +50,17 @@ PIE.IE9BorderImageRenderer = PIE.RendererBase.newRenderer( {
ROUND = me.ROUND,
ceil = Math.ceil,
- widths = props.width,
- widthT = ( widths ? widths.t : getLength( cs.borderTopWidth ) ).pixels( el ),
- widthR = ( widths ? widths.r : getLength( cs.borderRightWidth ) ).pixels( el ),
- widthB = ( widths ? widths.b : getLength( cs.borderBottomWidth ) ).pixels( el ),
- widthL = ( widths ? widths.l : getLength( cs.borderLeftWidth ) ).pixels( el ),
+ zero = PIE.getLength( '0' ),
+ widths = props.widths || ( borderProps ? borderProps.widths : { 't': zero, 'r': zero, 'b': zero, 'l': zero } ),
+ widthT = widths['t'].pixels( el ),
+ widthR = widths['r'].pixels( el ),
+ widthB = widths['b'].pixels( el ),
+ widthL = widths['l'].pixels( el ),
slices = props.slice,
- sliceT = slices.t.pixels( el ),
- sliceR = slices.r.pixels( el ),
- sliceB = slices.b.pixels( el ),
- sliceL = slices.l.pixels( el ),
+ sliceT = slices['t'].pixels( el ),
+ sliceR = slices['r'].pixels( el ),
+ sliceB = slices['b'].pixels( el ),
+ sliceL = slices['l'].pixels( el ),
centerW = elW - widthL - widthR,
middleH = elH - widthT - widthB,
imgCenterW = imgW - sliceL - sliceR,
View
@@ -27,6 +27,9 @@ if( !PIE ) {
'HR':1
},
+ /**
+ * Elements that can receive user focus
+ */
focusableElements: {
'A':1,
'INPUT':1,
@@ -35,6 +38,15 @@ if( !PIE ) {
'BUTTON':1
},
+ /**
+ * Values of the type attribute for input elements displayed as buttons
+ */
+ inputButtonTypes: {
+ 'submit':1,
+ 'button':1,
+ 'reset':1
+ },
+
emptyFn: function() {}
};
View
@@ -35,7 +35,7 @@ PIE.RendererBase = {
* renderer or any of the other renderers, e.g. things that might affect the
* element's size or style properties.
*/
- prepareUpdate: function() {},
+ prepareUpdate: PIE.emptyFn,
/**
* Tell the renderer to update based on modified properties
@@ -294,6 +294,63 @@ PIE.RendererBase = {
},
+ /**
+ * Hide the actual border of the element. In IE7 and up we can just set its color to transparent;
+ * however IE6 does not support transparent borders so we have to get tricky with it. Also, some elements
+ * like form buttons require removing the border width altogether, so for those we increase the padding
+ * by the border size.
+ */
+ hideBorder: function() {
+ var el = this.targetElement,
+ cs = el.currentStyle,
+ rs = el.runtimeStyle,
+ tag = el.tagName,
+ isIE6 = PIE.ieVersion === 6,
+ sides, side, i;
+
+ if( ( isIE6 && ( tag in PIE.childlessElements || tag === 'FIELDSET' ) ) ||
+ tag === 'BUTTON' || ( tag === 'INPUT' && el.type in PIE.inputButtonTypes ) ) {
+ rs.borderWidth = '';
+ sides = this.styleInfos.borderInfo.sides;
+ for( i = sides.length; i--; ) {
+ side = sides[ i ];
+ rs[ 'padding' + side ] = '';
+ rs[ 'padding' + side ] = ( PIE.getLength( cs[ 'padding' + side ] ) ).pixels( el ) +
+ ( PIE.getLength( cs[ 'border' + side + 'Width' ] ) ).pixels( el ) +
+ ( PIE.ieVersion !== 8 && i % 2 ? 1 : 0 ); //needs an extra horizontal pixel to counteract the extra "inner border" going away
+ }
+ rs.borderWidth = 0;
+ }
+ else if( isIE6 ) {
+ // Wrap all the element's children in a custom element, set the element to visiblity:hidden,
+ // and set the wrapper element to visiblity:visible. This hides the outer element's decorations
+ // (background and border) but displays all the contents.
+ // TODO find a better way to do this that doesn't mess up the DOM parent-child relationship,
+ // as this can interfere with other author scripts which add/modify/delete children. Also, this
+ // won't work for elements which cannot take children, e.g. input/button/textarea/img/etc. Look into
+ // using a compositor filter or some other filter which masks the border.
+ if( el.childNodes.length !== 1 || el.firstChild.tagName !== 'ie6-mask' ) {
+ var cont = doc.createElement( 'ie6-mask' ),
+ s = cont.style, child;
+ s.visibility = 'visible';
+ s.zoom = 1;
+ while( child = el.firstChild ) {
+ cont.appendChild( child );
+ }
+ el.appendChild( cont );
+ rs.visibility = 'hidden';
+ }
+ }
+ else {
+ rs.borderColor = 'transparent';
+ }
+ },
+
+ unhideBorder: function() {
+
+ },
+
+
/**
* Destroy the rendered objects. This is a base implementation which handles common renderer
* structures, but individual renderers may override as necessary.

0 comments on commit e270f7b

Please sign in to comment.