Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Allow border-image renderer to properly hide border on button/input e…
Browse files Browse the repository at this point in the history
…lements.
  • Loading branch information
Jason Johnston committed Sep 4, 2011
1 parent ded481a commit e270f7b
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 100 deletions.
46 changes: 24 additions & 22 deletions sources/BorderImageRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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 );
}
Expand Down
10 changes: 5 additions & 5 deletions sources/BorderImageStyleInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -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] )
};
}

Expand All @@ -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;
} );
}
Expand Down
61 changes: 0 additions & 61 deletions sources/BorderRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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).
Expand Down
22 changes: 11 additions & 11 deletions sources/IE9BorderImageRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions sources/PIE_open.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ if( !PIE ) {
'HR':1
},

/**
* Elements that can receive user focus
*/
focusableElements: {
'A':1,
'INPUT':1,
Expand All @@ -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() {}
};

Expand Down
59 changes: 58 additions & 1 deletion sources/RendererBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit e270f7b

Please sign in to comment.