@@ -433,51 +433,107 @@ angular.module('ui.bootstrap.position', [])
433
433
*/
434
434
positionElements : function ( hostElem , targetElem , placement , appendToBody ) {
435
435
hostElem = this . getRawNode ( hostElem ) ;
436
- targetElem = this . getRawNode ( targetElem ) ;
437
436
437
+ var hostElemPos = appendToBody ? this . offset ( hostElem ) : this . position ( hostElem ) ;
438
+ var viewportOffset = this . viewportOffset ( hostElem , appendToBody ) ;
439
+
440
+ return this . positionElement ( viewportOffset , hostElemPos , targetElem , placement ) ;
441
+ } ,
442
+
443
+ /**
444
+ * Provides coordinates for an element to be positioned at relative to
445
+ * the horizontal and vertical client coordinates. Passing 'auto' as part of the placement parameter
446
+ * will enable smart placement - where the element fits. i.e:
447
+ * 'auto left-top' will check to see if there is enough space to the left
448
+ * of the client coordinates to fit the targetElem, if not place right (same for secondary
449
+ * top placement). Available space is calculated using the client width and height.
450
+ *
451
+ * @param {element } clientCoordinates - The coordinates to position at.
452
+ * @param {element } targetElem - The element to position.
453
+ * @param {string= } [placement=top] - The placement for the targetElem,
454
+ * default is 'top'. 'center' is assumed as secondary placement for
455
+ * 'top', 'left', 'right', and 'bottom' placements. Available placements are:
456
+ * <ul>
457
+ * <li>top</li>
458
+ * <li>top-right</li>
459
+ * <li>top-left</li>
460
+ * <li>bottom</li>
461
+ * <li>bottom-left</li>
462
+ * <li>bottom-right</li>
463
+ * <li>left</li>
464
+ * <li>left-top</li>
465
+ * <li>left-bottom</li>
466
+ * <li>right</li>
467
+ * <li>right-top</li>
468
+ * <li>right-bottom</li>
469
+ * </ul>
470
+ *
471
+ * @returns {object } An object with the following properties:
472
+ * <ul>
473
+ * <li>**top**: Value for targetElem top.</li>
474
+ * <li>**left**: Value for targetElem left.</li>
475
+ * <li>**placement**: The resolved placement.</li>
476
+ * </ul>
477
+ */
478
+ positionElementAt : function ( clientCoordinates , targetElem , placement ) {
479
+ var viewportOffset = {
480
+ top : clientCoordinates . clientY ,
481
+ left : clientCoordinates . clientX ,
482
+ right : $document [ 0 ] . documentElement . clientWidth - clientCoordinates . clientX ,
483
+ bottom : $document [ 0 ] . documentElement . clientHeight - clientCoordinates . clientY
484
+ } ;
485
+ var hostPosition = {
486
+ top : clientCoordinates . clientY ,
487
+ left : clientCoordinates . clientX ,
488
+ height : 0 ,
489
+ width : 0
490
+ } ;
491
+ return this . positionElement ( viewportOffset , hostPosition , targetElem , placement ) ;
492
+ } ,
493
+
494
+ positionElement : function ( hostOffset , hostPos , targetElem , placement ) {
438
495
// need to read from prop to support tests.
439
496
var targetWidth = angular . isDefined ( targetElem . offsetWidth ) ? targetElem . offsetWidth : targetElem . prop ( 'offsetWidth' ) ;
440
497
var targetHeight = angular . isDefined ( targetElem . offsetHeight ) ? targetElem . offsetHeight : targetElem . prop ( 'offsetHeight' ) ;
441
498
499
+ targetElem = this . getRawNode ( targetElem ) ;
500
+
442
501
placement = this . parsePlacement ( placement ) ;
443
502
444
- var hostElemPos = appendToBody ? this . offset ( hostElem ) : this . position ( hostElem ) ;
445
503
var targetElemPos = { top : 0 , left : 0 , placement : '' } ;
446
504
447
505
if ( placement [ 2 ] ) {
448
- var viewportOffset = this . viewportOffset ( hostElem , appendToBody ) ;
449
-
450
506
var targetElemStyle = $window . getComputedStyle ( targetElem ) ;
451
507
var adjustedSize = {
452
508
width : targetWidth + Math . round ( Math . abs ( this . parseStyle ( targetElemStyle . marginLeft ) + this . parseStyle ( targetElemStyle . marginRight ) ) ) ,
453
509
height : targetHeight + Math . round ( Math . abs ( this . parseStyle ( targetElemStyle . marginTop ) + this . parseStyle ( targetElemStyle . marginBottom ) ) )
454
510
} ;
455
511
456
- placement [ 0 ] = placement [ 0 ] === 'top' && adjustedSize . height > viewportOffset . top && adjustedSize . height <= viewportOffset . bottom ? 'bottom' :
457
- placement [ 0 ] === 'bottom' && adjustedSize . height > viewportOffset . bottom && adjustedSize . height <= viewportOffset . top ? 'top' :
458
- placement [ 0 ] === 'left' && adjustedSize . width > viewportOffset . left && adjustedSize . width <= viewportOffset . right ? 'right' :
459
- placement [ 0 ] === 'right' && adjustedSize . width > viewportOffset . right && adjustedSize . width <= viewportOffset . left ? 'left' :
512
+ placement [ 0 ] = placement [ 0 ] === 'top' && adjustedSize . height > hostOffset . top && adjustedSize . height <= hostOffset . bottom ? 'bottom' :
513
+ placement [ 0 ] === 'bottom' && adjustedSize . height > hostOffset . bottom && adjustedSize . height <= hostOffset . top ? 'top' :
514
+ placement [ 0 ] === 'left' && adjustedSize . width > hostOffset . left && adjustedSize . width <= hostOffset . right ? 'right' :
515
+ placement [ 0 ] === 'right' && adjustedSize . width > hostOffset . right && adjustedSize . width <= hostOffset . left ? 'left' :
460
516
placement [ 0 ] ;
461
517
462
- placement [ 1 ] = placement [ 1 ] === 'top' && adjustedSize . height - hostElemPos . height > viewportOffset . bottom && adjustedSize . height - hostElemPos . height <= viewportOffset . top ? 'bottom' :
463
- placement [ 1 ] === 'bottom' && adjustedSize . height - hostElemPos . height > viewportOffset . top && adjustedSize . height - hostElemPos . height <= viewportOffset . bottom ? 'top' :
464
- placement [ 1 ] === 'left' && adjustedSize . width - hostElemPos . width > viewportOffset . right && adjustedSize . width - hostElemPos . width <= viewportOffset . left ? 'right' :
465
- placement [ 1 ] === 'right' && adjustedSize . width - hostElemPos . width > viewportOffset . left && adjustedSize . width - hostElemPos . width <= viewportOffset . right ? 'left' :
518
+ placement [ 1 ] = placement [ 1 ] === 'top' && adjustedSize . height - hostPos . height > hostOffset . bottom && adjustedSize . height - hostPos . height <= hostOffset . top ? 'bottom' :
519
+ placement [ 1 ] === 'bottom' && adjustedSize . height - hostPos . height > hostOffset . top && adjustedSize . height - hostPos . height <= hostOffset . bottom ? 'top' :
520
+ placement [ 1 ] === 'left' && adjustedSize . width - hostPos . width > hostOffset . right && adjustedSize . width - hostPos . width <= hostOffset . left ? 'right' :
521
+ placement [ 1 ] === 'right' && adjustedSize . width - hostPos . width > hostOffset . left && adjustedSize . width - hostPos . width <= hostOffset . right ? 'left' :
466
522
placement [ 1 ] ;
467
523
468
524
if ( placement [ 1 ] === 'center' ) {
469
525
if ( PLACEMENT_REGEX . vertical . test ( placement [ 0 ] ) ) {
470
- var xOverflow = hostElemPos . width / 2 - targetWidth / 2 ;
471
- if ( viewportOffset . left + xOverflow < 0 && adjustedSize . width - hostElemPos . width <= viewportOffset . right ) {
526
+ var xOverflow = hostPos . width / 2 - targetWidth / 2 ;
527
+ if ( hostOffset . left + xOverflow < 0 && adjustedSize . width - hostPos . width <= hostOffset . right ) {
472
528
placement [ 1 ] = 'left' ;
473
- } else if ( viewportOffset . right + xOverflow < 0 && adjustedSize . width - hostElemPos . width <= viewportOffset . left ) {
529
+ } else if ( hostOffset . right + xOverflow < 0 && adjustedSize . width - hostPos . width <= hostOffset . left ) {
474
530
placement [ 1 ] = 'right' ;
475
531
}
476
532
} else {
477
- var yOverflow = hostElemPos . height / 2 - adjustedSize . height / 2 ;
478
- if ( viewportOffset . top + yOverflow < 0 && adjustedSize . height - hostElemPos . height <= viewportOffset . bottom ) {
533
+ var yOverflow = hostPos . height / 2 - adjustedSize . height / 2 ;
534
+ if ( hostOffset . top + yOverflow < 0 && adjustedSize . height - hostPos . height <= hostOffset . bottom ) {
479
535
placement [ 1 ] = 'top' ;
480
- } else if ( viewportOffset . bottom + yOverflow < 0 && adjustedSize . height - hostElemPos . height <= viewportOffset . top ) {
536
+ } else if ( hostOffset . bottom + yOverflow < 0 && adjustedSize . height - hostPos . height <= hostOffset . top ) {
481
537
placement [ 1 ] = 'bottom' ;
482
538
}
483
539
}
@@ -486,37 +542,37 @@ angular.module('ui.bootstrap.position', [])
486
542
487
543
switch ( placement [ 0 ] ) {
488
544
case 'top' :
489
- targetElemPos . top = hostElemPos . top - targetHeight ;
545
+ targetElemPos . top = hostPos . top - targetHeight ;
490
546
break ;
491
547
case 'bottom' :
492
- targetElemPos . top = hostElemPos . top + hostElemPos . height ;
548
+ targetElemPos . top = hostPos . top + hostPos . height ;
493
549
break ;
494
550
case 'left' :
495
- targetElemPos . left = hostElemPos . left - targetWidth ;
551
+ targetElemPos . left = hostPos . left - targetWidth ;
496
552
break ;
497
553
case 'right' :
498
- targetElemPos . left = hostElemPos . left + hostElemPos . width ;
554
+ targetElemPos . left = hostPos . left + hostPos . width ;
499
555
break ;
500
556
}
501
557
502
558
switch ( placement [ 1 ] ) {
503
559
case 'top' :
504
- targetElemPos . top = hostElemPos . top ;
560
+ targetElemPos . top = hostPos . top ;
505
561
break ;
506
562
case 'bottom' :
507
- targetElemPos . top = hostElemPos . top + hostElemPos . height - targetHeight ;
563
+ targetElemPos . top = hostPos . top + hostPos . height - targetHeight ;
508
564
break ;
509
565
case 'left' :
510
- targetElemPos . left = hostElemPos . left ;
566
+ targetElemPos . left = hostPos . left ;
511
567
break ;
512
568
case 'right' :
513
- targetElemPos . left = hostElemPos . left + hostElemPos . width - targetWidth ;
569
+ targetElemPos . left = hostPos . left + hostPos . width - targetWidth ;
514
570
break ;
515
571
case 'center' :
516
572
if ( PLACEMENT_REGEX . vertical . test ( placement [ 0 ] ) ) {
517
- targetElemPos . left = hostElemPos . left + hostElemPos . width / 2 - targetWidth / 2 ;
573
+ targetElemPos . left = hostPos . left + hostPos . width / 2 - targetWidth / 2 ;
518
574
} else {
519
- targetElemPos . top = hostElemPos . top + hostElemPos . height / 2 - targetHeight / 2 ;
575
+ targetElemPos . top = hostPos . top + hostPos . height / 2 - targetHeight / 2 ;
520
576
}
521
577
break ;
522
578
}
0 commit comments