@@ -303,6 +303,7 @@ define(function (require, exports) {
303303 function attachCloseEvents ( ) {
304304 $ ( "html" ) . on ( "click" , closeDropdown ) ;
305305 $ ( "#project-files-container" ) . on ( "scroll" , closeDropdown ) ;
306+ $ ( "#git-panel .table-container" ) . on ( "scroll" , closeDropdown ) ;
306307 $ ( "#titlebar .nav" ) . on ( "click" , closeDropdown ) ;
307308
308309 currentEditor = EditorManager . getCurrentFullEditor ( ) ;
@@ -316,6 +317,7 @@ define(function (require, exports) {
316317 function detachCloseEvents ( ) {
317318 $ ( "html" ) . off ( "click" , closeDropdown ) ;
318319 $ ( "#project-files-container" ) . off ( "scroll" , closeDropdown ) ;
320+ $ ( "#git-panel .table-container" ) . off ( "scroll" , closeDropdown ) ;
319321 $ ( "#titlebar .nav" ) . off ( "click" , closeDropdown ) ;
320322
321323 if ( currentEditor ) {
@@ -327,8 +329,59 @@ define(function (require, exports) {
327329 $dropdown = null ;
328330 }
329331
332+ function _positionDropdownBelow ( $toggle ) {
333+ // two margins to account for the preceding project dropdown as well
334+ const marginLeft = ( parseInt ( $toggle . css ( "margin-left" ) , 10 ) * 2 ) || 0 ;
335+
336+ const toggleOffset = $toggle . offset ( ) ;
337+
338+ $dropdown
339+ . css ( {
340+ left : toggleOffset . left - marginLeft + 3 ,
341+ top : toggleOffset . top + $toggle . outerHeight ( ) - 3
342+ } )
343+ . appendTo ( $ ( "body" ) ) ;
344+
345+ // fix so it doesn't overflow the screen
346+ const maxHeight = $dropdown . parent ( ) . height ( ) ,
347+ height = $dropdown . height ( ) ,
348+ topOffset = $dropdown . position ( ) . top ;
349+ if ( height + topOffset >= maxHeight - 10 ) {
350+ $dropdown . css ( "bottom" , "10px" ) ;
351+ }
352+ }
353+
354+ function _positionDropdownAbove ( $anchor ) {
355+ const anchorOffset = $anchor . offset ( ) ;
356+
357+ $dropdown
358+ . css ( {
359+ left : anchorOffset . left ,
360+ // the .dropdown-menu class positions with "top: 100%", it has to be
361+ // explicitly overridden or the bottom positioning below is over-constrained
362+ top : "auto" ,
363+ bottom : $ ( window ) . height ( ) - anchorOffset . top + 3 ,
364+ // grow upwards from the anchor instead of the default top-left origin
365+ "transform-origin" : "0 100%"
366+ } )
367+ . appendTo ( $ ( "body" ) ) ;
368+
369+ // fix so it doesn't overflow the screen
370+ if ( $dropdown . height ( ) >= anchorOffset . top - 10 ) {
371+ $dropdown . css ( "top" , "10px" ) ;
372+ }
373+
374+ const rightOverflow = $dropdown . offset ( ) . left + $dropdown . outerWidth ( ) - ( $ ( window ) . width ( ) - 10 ) ;
375+ if ( rightOverflow > 0 ) {
376+ $dropdown . css ( "left" , anchorOffset . left - rightOverflow ) ;
377+ }
378+ }
379+
330380 function toggleDropdown ( e ) {
331381 e . stopPropagation ( ) ;
382+ // currentTarget is only valid while the event is being dispatched,
383+ // so it has to be captured before the async branch listing below
384+ const $anchor = $ ( e . currentTarget ) ;
332385
333386 // If the dropdown is already visible, close it
334387 if ( $dropdown ) {
@@ -349,25 +402,11 @@ define(function (require, exports) {
349402 } , [ ] ) ;
350403
351404 $dropdown = $ ( renderList ( branches ) ) ;
352- const $toggle = $ ( "#git-branch-dropdown-toggle" ) ;
353- // two margins to account for the preceding project dropdown as well
354- const marginLeft = ( parseInt ( $toggle . css ( "margin-left" ) , 10 ) * 2 ) || 0 ;
355-
356- const toggleOffset = $toggle . offset ( ) ;
357-
358- $dropdown
359- . css ( {
360- left : toggleOffset . left - marginLeft + 3 ,
361- top : toggleOffset . top + $toggle . outerHeight ( ) - 3
362- } )
363- . appendTo ( $ ( "body" ) ) ;
364-
365- // fix so it doesn't overflow the screen
366- var maxHeight = $dropdown . parent ( ) . height ( ) ,
367- height = $dropdown . height ( ) ,
368- topOffset = $dropdown . position ( ) . top ;
369- if ( height + topOffset >= maxHeight - 10 ) {
370- $dropdown . css ( "bottom" , "10px" ) ;
405+ if ( $anchor . closest ( "#git-panel" ) . length ) {
406+ // the git panel sits at the bottom of the screen, open upwards from there
407+ _positionDropdownAbove ( $anchor ) ;
408+ } else {
409+ _positionDropdownBelow ( $ ( "#git-branch-dropdown-toggle" ) ) ;
371410 }
372411
373412 PopUpManager . addPopUp ( $dropdown , detachCloseEvents , true , { closeCurrentPopups : true } ) ;
@@ -442,6 +481,7 @@ define(function (require, exports) {
442481 . off ( "click" )
443482 . text ( "not a git repo" ) ;
444483 Panel . setBranchName ( "not a git repo" , "" ) ;
484+ $ ( "#git-panel .git-panel-branch" ) . removeClass ( "clickable" ) . off ( "click" ) ;
445485 Panel . disable ( "not-repo" ) ;
446486
447487 return ;
@@ -485,6 +525,10 @@ define(function (require, exports) {
485525 . off ( "click" )
486526 . on ( "click" , toggleDropdown ) ;
487527 Panel . setBranchName ( branchName , tooltip ) ;
528+ $ ( "#git-panel .git-panel-branch" )
529+ . addClass ( "clickable" )
530+ . off ( "click" )
531+ . on ( "click" , toggleDropdown ) ;
488532 Panel . enable ( ) ;
489533
490534 } ) . catch ( function ( err ) {
@@ -497,6 +541,7 @@ define(function (require, exports) {
497541 . off ( "click" )
498542 . text ( "no branch" ) ;
499543 Panel . setBranchName ( "no branch" , "" ) ;
544+ $ ( "#git-panel .git-panel-branch" ) . removeClass ( "clickable" ) . off ( "click" ) ;
500545 Panel . enable ( ) ;
501546 } else {
502547 throw ex ;
0 commit comments