@ -249,12 +249,14 @@
} ,
} ,
_getLeftAlignPosition : function ( combo , popup , extraWidth , container ) {
_getLeftAlignPosition : function ( combo , popup , extraWidth , container ) {
var viewBounds = popup . element . bounds ( ) ,
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
var left = combo . element . offset ( ) . left - ( container ? container . getBoundingClientRect ( ) . left : 0 ) + extraWidth ;
viewportRect = document . documentElement . getBoundingClientRect ( ) ,
containerRect = container ? container . getBoundingClientRect ( ) : { left : 0 } ;
var left = comboRect . left - containerRect . left + extraWidth ;
if ( left + viewBounds . width > windowBounds . width ) {
if ( comboRect . left + popupRect . width > viewportRect . width ) {
left = windowBounds . width - viewBounds . width ;
left = viewportRect . width - popupRect . width - containerRect . left ;
}
}
return left ;
return left ;
} ,
} ,
@ -263,12 +265,13 @@
var left = this . _getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
var left = this . _getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
var dir = "" ;
var dir = "" ;
// 如果放不下,优先使用RightAlign, 如果RightAlign也放不下, 再使用left=0
// 如果放不下,优先使用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 ) ;
left = this . _getRightAlignPosition ( combo , popup , extraWidth ) ;
dir = "left" ;
dir = "left" ;
}
}
if ( left < 0 ) {
if ( left + containerRect . left < 0 ) {
left = 0 ;
left = 0 - containerRect . left ;
}
}
return {
return {
left : left ,
left : left ,
@ -285,17 +288,19 @@
} ;
} ;
} ,
} ,
_getRightAlignPosition : function ( combo , popup , extraWidth ) {
_getRightAlignPosition : function ( combo , popup , extraWidth , container ) {
var comboBounds = combo . element . bounds ( ) , viewBounds = popup . element . bounds ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
return combo . element . offset ( ) . left + comboBounds . width - viewBounds . width - extraWidth ;
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 ) {
getRightAlignPosition : function ( combo , popup , extraWidth , container ) {
var left = this . _getRightAlignPosition ( combo , popup , extraWidth ) ;
var left = this . _getRightAlignPosition ( combo , popup , extraWidth , container ) ;
var dir = "" ;
var dir = "" ;
// 如果放不下,优先使用LeftAlign, 如果LeftAlign也放不下, 再使用left=0
// 如果放不下,优先使用LeftAlign, 如果LeftAlign也放不下, 再使用left=0
if ( left < 0 ) {
if ( left < 0 ) {
left = this . _getLeftAlignPosition ( combo , popup , extraWidth ) ;
left = this . _getLeftAlignPosition ( combo , popup , extraWidth , container ) ;
dir = "right" ;
dir = "right" ;
}
}
if ( left < 0 ) {
if ( left < 0 ) {
@ -317,14 +322,13 @@
} ,
} ,
getTopAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
getTopAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ,
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
var top , adaptHeight , dir ;
var top , adaptHeight , dir ;
if ( BI . DOM . isBottomSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
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 ) {
} else if ( needAdaptHeight ) {
top = comboBounds . top - containerBounds . top + extraHeight ;
top = comboBounds . top - containerBounds . top + extraHeight ;
adaptHeight = viewportBounds . height - comboBounds . top ;
adaptHeight = viewportBounds . height - comboBounds . top ;
@ -375,20 +379,19 @@
} ,
} ,
getBottomAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
getBottomAlignPosition : function ( combo , popup , extraHeight , needAdaptHeight , container ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ,
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
containerBounds = container ? container . getBoundingClientRect ( ) : { top : 0 } ;
var top , adaptHeight , dir ;
var top , adaptHeight , dir ;
if ( BI . DOM . isTopSpaceEnough ( combo , popup , - 1 * comboBounds . height + extraHeight ) ) {
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 ) {
} else if ( needAdaptHeight ) {
top = 0 - containerBounds . top ;
top = 0 - containerBounds . top ;
adaptHeight = comboBounds . top + comboBounds . height - extraHeight ;
adaptHeight = comboBounds . top + comboBounds . height - extraHeight ;
} else if ( BI . DOM . isBottomSpaceEnough ( combo , popup , - 1 * 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" ;
dir = "bottom" ;
} else {
} else {
top = 0 ;
top = 0 ;
@ -410,16 +413,15 @@
} ,
} ,
getBottomAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight ) {
getBottomAdaptPosition : function ( combo , popup , extraHeight , needAdaptHeight ) {
var comboOffset = combo . element . offset ( ) ;
var comboBounds = combo . element [ 0 ] . getBoundingClientRect ( ) , popupBounds = popup . element [ 0 ] . getBoundingClientRect ( ) ,
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
if ( BI . DOM . isBottomSpaceEnough ( combo , popup , extraHeight ) ) {
if ( BI . DOM . isBottomSpaceEnough ( combo , popup , extraHeight ) ) {
return BI . DOM . getBottomPosition ( combo , popup , extraHeight ) ;
return BI . DOM . getBottomPosition ( combo , popup , extraHeight ) ;
}
}
if ( needAdaptHeight ) {
if ( needAdaptHeight ) {
return {
return {
top : comboOffset . top + comboBounds . height + extraHeight ,
top : comboBounds . top + comboBounds . height + extraHeight ,
adaptHeight : windowBounds . height - comboOffset . top - comboBounds . height - extraHeight
adaptHeight : windowBounds . height - comboBounds . top - comboBounds . height - extraHeight
} ;
} ;
}
}
if ( popupBounds . height + extraHeight > windowBounds . height ) {
if ( popupBounds . height + extraHeight > windowBounds . height ) {
@ -433,17 +435,18 @@
} ;
} ;
} ,
} ,
getCenterAdaptPosition : function ( combo , popup ) {
getCenterAdaptPosition : function ( combo , popup , positionRelativeElement ) {
var comboOffset = combo . element . offset ( ) ;
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var left ;
var left ;
if ( comboOffse t . left + comboBounds . width / 2 + popupBounds . width / 2 > window Bounds. width ) {
if ( comboRec t . left + comboRect . width / 2 + popupRect . width / 2 > viewport Bounds. width ) {
left = window Bounds. width - popupBounds . width ;
left = viewport Bounds. width - comboRect . width - positionRelativeElementRect . left ;
} else {
} 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 ;
left = 0 ;
}
}
return {
return {
@ -451,17 +454,19 @@
} ;
} ;
} ,
} ,
getMiddleAdaptPosition : function ( combo , popup ) {
getMiddleAdaptPosition : function ( combo , popup , positionRelativeElement ) {
var comboOffset = combo . element . offset ( ) ;
var comboRect = combo . element [ 0 ] . getBoundingClientRect ( ) ,
var comboBounds = combo . element . bounds ( ) , popupBounds = popup . element . bounds ( ) ,
popupRect = popup . element [ 0 ] . getBoundingClientRect ( ) ,
windowBounds = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) ;
positionRelativeElementRect = positionRelativeElement . getBoundingClientRect ( ) ,
viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var top ;
var top ;
if ( comboOffset . top + comboBounds . height / 2 + popupBounds . height / 2 > windowBounds . height ) {
if ( comboRec t . top + comboRect . height / 2 + popupRect . height / 2 > viewport Bounds. height ) {
top = window Bounds. height - popupBounds . height ;
top = viewport Bounds. height - popupRect . height - positionRelativeElementRect . top ;
} else {
} 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 ;
top = 0 ;
}
}
return {
return {
@ -674,32 +679,32 @@
getComboPosition : function ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions , offsetStyle , positionRelativeElement ) {
getComboPosition : function ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions , offsetStyle , positionRelativeElement ) {
extraWidth || ( extraWidth = 0 ) ;
extraWidth || ( extraWidth = 0 ) ;
extraHeight || ( extraHeight = 0 ) ;
extraHeight || ( extraHeight = 0 ) ;
var bodyHeight = BI . Widget . _renderEngine . createElement ( "body" ) . bounds ( ) . height - extraHeight ;
var viewportBounds = document . documentElement . getBoundingClientRect ( ) ;
var maxHeight = Math . min ( popup . attr ( "maxHeight" ) || bodyHeight , bodyH eight) ;
var maxHeight = Math . min ( popup . attr ( "maxHeight" ) || viewportBounds . height , viewportBounds . h eight) ;
popup . resetHeight && popup . resetHeight ( maxHeight ) ;
popup . resetHeight && popup . resetHeight ( maxHeight ) ;
var position = BI . DOM . getComboPositionByDirections ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions || [ "bottom" , "top" , "right" , "left" ] , positionRelativeElement ) ;
var position = BI . DOM . getComboPositionByDirections ( combo , popup , extraWidth , extraHeight , needAdaptHeight , directions || [ "bottom" , "top" , "right" , "left" ] , positionRelativeElement ) ;
switch ( offsetStyle ) {
switch ( offsetStyle ) {
case "center" :
case "center" :
if ( position . change ) {
if ( position . change ) {
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . top = p . top ;
position . top = p . top ;
} else {
} else {
var p = BI . DOM . getCenterAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getCenterAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . left = p . left ;
position . left = p . left ;
}
}
break ;
break ;
case "middle" :
case "middle" :
if ( position . change ) {
if ( position . change ) {
var p = BI . DOM . getCenterAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getCenterAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . left = p . left ;
position . left = p . left ;
} else {
} else {
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup ) ;
var p = BI . DOM . getMiddleAdaptPosition ( combo , popup , positionRelativeElement ) ;
position . top = p . top ;
position . top = p . top ;
}
}
break ;
break ;
}
}
if ( needAdaptHeight === true ) {
if ( needAdaptHeight === true ) {
popup . resetHeight && popup . resetHeight ( Math . min ( bodyH eight - position . top + ( positionRelativeElement ? positionRelativeElement . getBoundingClientRect ( ) . top : 0 ) , maxHeight ) ) ;
popup . resetHeight && popup . resetHeight ( Math . min ( viewportBounds . h eight - position . top + ( positionRelativeElement ? positionRelativeElement . getBoundingClientRect ( ) . top : 0 ) , maxHeight ) ) ;
}
}
return position ;
return position ;
} ,
} ,
@ -729,5 +734,19 @@
return BI . DOM . getPositionRelativeContainingBlock ( element . parentNode ) ;
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
} ;
} ,
} ) ;
} ) ;
} ) ( ) ;
} ) ( ) ;