@ -239,22 +239,26 @@
} ,
isRightSpaceLarger : function ( combo ) {
var windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
return windowBounds . width - combo . element . offset ( ) . left - combo . element . bounds ( ) . width >= combo . element . offset ( ) . left ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
return viewportBounds . width - comboBounds . right >= comboBounds . left ;
} ,
isBottomSpaceLarger : function ( combo ) {
var windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
return windowBounds . height - combo . element . offset ( ) . top - combo . element . bounds ( ) . height >= combo . element . offset ( ) . top ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
return viewportBounds . height - comboBounds . bottom >= comboBounds . top ;
} ,
_getLeftAlignPosition : function ( combo , popup , extraWidth , container ) {
var viewBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
var left = combo . element . offset ( ) . left - ( container ? container . getBoundingClientRect ( ) . left : 0 ) + extraWidth ;
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
viewportRect = document . documentElement . getBoundingClientRect ( ) ,
containerRect = container ? container . getBoundingClientRect ( ) : { left : 0 } ;
var left = comboRect . left - containerRect . left + extraWidth ;
if ( left + viewBounds . width > windowBounds . width ) {
left = windowBounds . width - viewBounds . width ;
if ( comboRect . left + popupRect . width > viewportRect . width ) {
left = viewportRect . width - popupRect . width - containerRect . left ;
}
return left ;
} ,
@ -263,12 +267,13 @@
var left = this . _getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
var dir = "" ;
// 如果放不下,优先使用RightAlign, 如果RightAlign也放不下, 再使用left=0
if ( left < 0 ) {
var containerRect = container ? container . getBoundingClientRect ( ) : { left : 0 } ;
if ( left + containerRect . left < 0 ) {
left = this . _getRightAlignPosition ( combo , popup , extraWidth ) ;
dir = "left" ;
}
if ( left < 0 ) {
left = 0 ;
if ( left + containerRect . left < 0 ) {
left = 0 - containerRect . left ;
}
return {
left : left ,
@ -276,26 +281,28 @@
} ;
} ,
getLeftAdaptPosition : function ( combo , popup , extraWidth ) {
if ( BI . DOM . isLeftSpaceEnough ( combo , popup , extraWidth ) ) {
return BI . DOM . getLeftPosition ( combo , popup , extraWidth ) ;
getLeftAdaptPosition : function ( combo , popup , extraWidth , container ) {
if ( BI . DOM . isLeftSpaceEnough ( combo , popup , extraWidth , container ) ) {
return BI . DOM . getLeftPosition ( combo , popup , extraWidth , container ) ;
}
return {
left : 0
} ;
} ,
_getRightAlignPosition : function ( combo , popup , extraWidth ) {
var comboBounds = combo . element . bounds ( ) , viewBounds = popup . element . bounds ( ) ;
return combo . element . offset ( ) . left + comboBounds . width - viewBounds . width - extraWidth ;
_getRightAlignPosition : function ( combo , popup , extraWidth , container ) {
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
viewBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
containerRect = container ? container . getBoundingClientRect ( ) : { left : 0 } ;
return comboBounds . left + comboBounds . width - viewBounds . width - extraWidth - containerRect . left ;
} ,
getRightAlignPosition : function ( combo , popup , extraWidth ) {
var left = this . _getRightAlignPosition ( combo , popup , extraWidth ) ;
getRightAlignPosition : function ( combo , popup , extraWidth , container ) {
var left = this . _getRightAlignPosition ( combo , popup , extraWidth , container ) ;
var dir = "" ;
// 如果放不下,优先使用LeftAlign, 如果LeftAlign也放不下, 再使用left=0
if ( left < 0 ) {
left = this . _getLeftAlignPosition ( combo , popup , extraWidth ) ;
left = this . _getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
dir = "right" ;
}
if ( left < 0 ) {
@ -307,27 +314,26 @@
} ;
} ,
getRightAdaptPosition : function ( combo , popup , extraWidth ) {
if ( BI . DOM . isRightSpaceEnough ( combo , popup , extraWidth ) ) {
return BI . DOM . getRightPosition ( combo , popup , extraWidth ) ;
getRightAdaptPosition : function ( combo , popup , extraWidth , container ) {
if ( BI . DOM . isRightSpaceEnough ( combo , popup , extraWidth , container ) ) {
return BI . DOM . getRightPosition ( combo , popup , extraWidth , container ) ;
}
return {
left : BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) . width - popup . element . bounds ( ) . width
left : document . documentElement . getBoundingClientRect ( ) . width - popup . element [ 0 ] . getBoundingClientRect ( ) . width - container . getBoundingClientRect ( ) . left
} ;
} ,
getTopAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ,
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
var top , adaptHeight , dir ;
if ( BI . DOM . isBottomSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
top = comboOffset . top - containerBounds . top + extraHeight ;
top = comboBounds . top - containerBounds . top + extraHeight ;
} else if ( needAdaptHeight ) {
top = comboBounds . top - containerBounds . top + extraHeight ;
adaptHeight = viewportBounds . height - top ;
adaptHeight = viewportBounds . height - comboBounds . top ;
} else if ( BI . DOM . isTopSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
// 下方空间不足且不允许调整高度的情况下,优先使用上对齐
top = comboBounds . top + comboBounds . height - popupBounds . height - containerBounds . top - extraHeight ;
@ -351,44 +357,45 @@
} ;
} ,
getTopAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight ) {
var popupBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
getTopAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight , positionRelativeElement ) {
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
if ( BI . DOM . isTopSpaceEnough ( combo , popup , extraHeight ) ) {
return BI . DOM . getTopPosition ( combo , popup , extraHeight ) ;
}
if ( needAdaptHeight ) {
return {
top : 0 ,
adaptHeight : combo . element . offset ( ) . top - extraHeight
top : 0 - positionRelativeElementRect . top ,
adaptHeight : comboBounds . top - extraHeight
} ;
}
if ( popupBounds . height + extraHeight > window Bounds. height ) {
if ( popupBounds . height + extraHeight > viewport Bounds. height ) {
return {
top : 0 ,
adaptHeight : window Bounds. height - extraHeight
top : 0 - positionRelativeElementRect . top ,
adaptHeight : viewport Bounds. height - extraHeight
} ;
}
return {
top : 0
top : 0 - positionRelativeElementRect . top
} ;
} ,
getBottomAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ,
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
var top , adaptHeight , dir ;
if ( BI . DOM . isTopSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
top = comboOffset . top + comboBounds . height - containerBounds . top - popupBounds . height ;
top = comboBounds . top + comboBounds . height - containerBounds . top - popupBounds . height ;
} else if ( needAdaptHeight ) {
top = 0 - containerBounds . top ;
adaptHeight = comboBounds . top + comboBounds . height - extraHeight ;
} else if ( BI . DOM . isBottomSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
// 上方空间不足且不允许调整高度的情况下,优先使用下对齐
top = comboOffset . top - containerBounds . top + extraHeight ;
top = comboBounds . top - containerBounds . top + extraHeight ;
dir = "bottom" ;
} else {
top = 0 ;
@ -409,41 +416,43 @@
} ;
} ,
getBottomAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
getBottomAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight , positionRelativeElement ) {
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ,
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ;
if ( BI . DOM . isBottomSpaceEnough ( combo , popup , extraHeight ) ) {
return BI . DOM . getBottomPosition ( combo , popup , extraHeight ) ;
return BI . DOM . getBottomPosition ( combo , popup , extraHeight , positionRelativeElement ) ;
}
if ( needAdaptHeight ) {
return {
top : comboOffset . top + comboBounds . height + extraHeight ,
adaptHeight : window Bounds. height - comboOffset . top - comboBounds . height - extraHeight
top : comboBounds . top + comboBounds . height + extraHeight - positionRelativeElementRect . top ,
adaptHeight : viewport Bounds. height - comboBounds . top - comboBounds . height - extraHeight
} ;
}
if ( popupBounds . height + extraHeight > window Bounds. height ) {
if ( popupBounds . height + extraHeight > viewport Bounds. height ) {
return {
top : extraHeight ,
adaptHeight : window Bounds. height - extraHeight
top : extraHeight - positionRelativeElementRect . top ,
adaptHeight : viewport Bounds. height - extraHeight
} ;
}
return {
top : window Bounds. height - popupBounds . height - extraHeight
top : viewport Bounds. height - popupBounds . height - extraHeight - positionRelativeElementRect . top
} ;
} ,
getCenterAdaptPosition : function ( combo , popup ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
getCenterAdaptPosition : function ( combo , popup , positionRelativeElement ) {
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var left ;
if ( comboOffse t . left + comboBounds . width / 2 + popupBounds . width / 2 > window Bounds. width ) {
left = window Bounds. width - popupBounds . width ;
if ( comboRec t . left + comboRect . width / 2 + popupRect . width / 2 > viewport Bounds. width ) {
left = viewport Bounds. width - comboRect . width - positionRelativeElementRect . left ;
} else {
left = comboOffset . left + comboBounds . width / 2 - popupBounds . width / 2 ;
left = comboRect . left + ( comboRect . width - popupRect . width ) / 2 - positionRelativeElementRect . left ;
}
if ( left < 0 ) {
if ( left + positionRelativeElementRect . left < 0 ) {
left = 0 ;
}
return {
@ -451,17 +460,19 @@
} ;
} ,
getMiddleAdaptPosition : function ( combo , popup ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
getMiddleAdaptPosition : function ( combo , popup , positionRelativeElement ) {
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var top ;
if ( comboOffset . top + comboBounds . height / 2 + popupBounds . height / 2 > windowBounds . height ) {
top = window Bounds. height - popupBounds . height ;
if ( comboRec t . top + comboRect . height / 2 + popupRect . height / 2 > viewport Bounds. height ) {
top = viewport Bounds. height - popupRect . height - positionRelativeElementRect . top ;
} else {
top = comboOffset . top + comboBounds . height / 2 - popupBounds . height / 2 ;
top = comboRect . top + ( comboRect . height - popupRect . height ) / 2 - positionRelativeElementRect . top ;
}
if ( top < 0 ) {
if ( top + positionRelativeElementRect . top < 0 ) {
top = 0 ;
}
return {
@ -633,10 +644,10 @@
case "left" :
case "right" :
if ( BI . DOM . isRightSpaceLarger ( combo ) ) {
left = BI . DOM . getRightAdaptPosition ( combo , popup , extraWidth ) . left ;
left = BI . DOM . getRightAdaptPosition ( combo , popup , extraWidth , container ) . left ;
firstDir = "right" ;
} else {
left = BI . DOM . getLeftAdaptPosition ( combo , popup , extraWidth ) . left ;
left = BI . DOM . getLeftAdaptPosition ( combo , popup , extraWidth , container ) . left ;
firstDir = "left" ;
}
if ( topBottom [ 0 ] === "bottom" ) {
@ -651,19 +662,19 @@
return pos ;
default :
if ( BI . DOM . isBottomSpaceLarger ( combo ) ) {
top = BI . DOM . getBottomAdaptPosition ( combo , popup , extraHeight , needAdaptHeight ) . top ;
top = BI . DOM . getBottomAdaptPosition ( combo , popup , extraHeight , needAdaptHeight , container ) . top ;
firstDir = "bottom" ;
} else {
top = BI . DOM . getTopAdaptPosition ( combo , popup , extraHeight , needAdaptHeight ) . top ;
top = BI . DOM . getTopAdaptPosition ( combo , popup , extraHeight , needAdaptHeight , container ) . top ;
firstDir = "top" ;
}
if ( leftRight [ 0 ] === "right" ) {
pos = BI . DOM . getLeftAlignPosition ( combo , popup , extraWidth ) ;
pos = BI . DOM . getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
pos . top = top ;
pos . dir = firstDir + "," + pos . dir ;
return pos ;
}
pos = BI . DOM . getRightAlignPosition ( combo , popup , extraWidth ) ;
pos = BI . DOM . getRightAlignPosition ( combo , popup , extraWidth , container ) ;
pos . top = top ;
pos . dir = firstDir + "," + pos . dir ;
return pos ;
@ -671,35 +682,35 @@
} ,
getComboPosition : function ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions , offsetStyle , container ) {
getComboPosition : function ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions , offsetStyle , positionRelativeElement ) {
extraWidth || ( extraWidth = 0 ) ;
extraHeight || ( extraHeight = 0 ) ;
var bodyHeight = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) . height - extraHeight ;
var maxHeight = Math . min ( popup . attr ( "maxHeight" ) || bodyHeight , bodyH eight) ;
var viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var maxHeight = Math . min ( popup . attr ( "maxHeight" ) || viewportBounds . height , viewportBounds . h eight) ;
popup . resetHeight && popup . resetHeight ( maxHeight ) ;
var position = BI . DOM . getComboPositionByDirections ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions || [ "bottom" , "top" , "right" , "left" ] , container ) ;
var position = BI . DOM . getComboPositionByDirections ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions || [ "bottom" , "top" , "right" , "left" ] , positionRelativeElement ) ;
switch ( offsetStyle ) {
case "center" :
if ( position . change ) {
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . top = p . top ;
} else {
var p = BI . DOM . getCenterAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getCenterAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . left = p . left ;
}
break ;
case "middle" :
if ( position . change ) {
var p = BI . DOM . getCenterAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getCenterAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . left = p . left ;
} else {
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . top = p . top ;
}
break ;
}
if ( needAdaptHeight === true ) {
popup . resetHeight && popup . resetHeight ( Math . min ( bodyH eight - position . top , maxHeight ) ) ;
popup . resetHeight && popup . resetHeight ( Math . min ( viewportBounds . h eight - position . top + ( positionRelativeElement ? positionRelativeElement . getBoundingClientRect ( ) . top : 0 ) , maxHeight ) ) ;
}
return position ;
} ,
@ -729,5 +740,19 @@
return BI . DOM . getPositionRelativeContainingBlock ( element . parentNode ) ;
} ,
/ * *
* 获取position : fixed相对定位的元素的clientRect
* /
getPositionRelativeContainingBlockRect : function ( element ) {
var positionRelativeElement = BI . DOM . getPositionRelativeContainingBlock ( element ) ;
var rect = positionRelativeElement . getBoundingClientRect ( ) ;
return {
... rect . toJSON ( ) ,
scaleX : rect . width / positionRelativeElement . offsetWidth ,
scaleY : rect . height / positionRelativeElement . offsetHeight
} ;
} ,
} ) ;
} ) ( ) ;