2019-05-01 04:31:12 +08:00
/ * !
* Draggabilly PACKAGED v2 . 2.0
* Make that shiz draggable
* https : //draggabilly.desandro.com
* MIT license
* /
2019-05-13 03:45:30 +08:00
import optionsInit from './options_init.js' ;
2019-05-01 04:31:12 +08:00
! function ( i , e ) { "function" == typeof define && define . amd ? define ( "jquery-bridget/jquery-bridget" , [ "jquery" ] , function ( t ) { return e ( i , t ) } ) : "object" == typeof module && module . exports ? module . exports = e ( i , require ( "jquery" ) ) : i . jQueryBridget = e ( i , i . jQuery ) } ( window , function ( t , i ) { "use strict" ; var c = Array . prototype . slice , e = t . console , p = void 0 === e ? function ( ) { } : function ( t ) { e . error ( t ) } ; function n ( d , o , u ) { ( u = u || i || t . jQuery ) && ( o . prototype . option || ( o . prototype . option = function ( t ) { u . isPlainObject ( t ) && ( this . options = u . extend ( ! 0 , this . options , t ) ) } ) , u . fn [ d ] = function ( t ) { if ( "string" == typeof t ) { var i = c . call ( arguments , 1 ) ; return s = i , a = "$()." + d + '("' + ( r = t ) + '")' , ( e = this ) . each ( function ( t , i ) { var e = u . data ( i , d ) ; if ( e ) { var n = e [ r ] ; if ( n && "_" != r . charAt ( 0 ) ) { var o = n . apply ( e , s ) ; h = void 0 === h ? o : h } else p ( a + " is not a valid method" ) } else p ( d + " not initialized. Cannot call methods, i.e. " + a ) } ) , void 0 !== h ? h : e } var e , r , s , h , a , n ; return n = t , this . each ( function ( t , i ) { var e = u . data ( i , d ) ; e ? ( e . option ( n ) , e . _init ( ) ) : ( e = new o ( i , n ) , u . data ( i , d , e ) ) } ) , this } , r ( u ) ) } function r ( t ) { ! t || t && t . bridget || ( t . bridget = n ) } return r ( i || t . jQuery ) , n } ) , function ( t , i ) { "use strict" ; "function" == typeof define && define . amd ? define ( "get-size/get-size" , [ ] , function ( ) { return i ( ) } ) : "object" == typeof module && module . exports ? module . exports = i ( ) : t . getSize = i ( ) } ( window , function ( ) { "use strict" ; function m ( t ) { var i = parseFloat ( t ) ; return - 1 == t . indexOf ( "%" ) && ! isNaN ( i ) && i } var e = "undefined" == typeof console ? function ( ) { } : function ( t ) { console . error ( t ) } , y = [ "paddingLeft" , "paddingRight" , "paddingTop" , "paddingBottom" , "marginLeft" , "marginRight" , "marginTop" , "marginBottom" , "borderLeftWidth" , "borderRightWidth" , "borderTopWidth" , "borderBottomWidth" ] , b = y . length ; function E ( t ) { var i = getComputedStyle ( t ) ; return i || e ( "Style returned " + i + ". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1" ) , i } var _ , x = ! 1 ; function P ( t ) { if ( function ( ) { if ( ! x ) { x = ! 0 ; var t = document . createElement ( "div" ) ; t . style . width = "200px" , t . style . padding = "1px 2px 3px 4px" , t . style . borderStyle = "solid" , t . style . borderWidth = "1px 2px 3px 4px" , t . style . boxSizing = "border-box" ; var i = document . body || document . documentElement ; i . appendChild ( t ) ; var e = E ( t ) ; P . isBoxSizeOuter = _ = 200 == m ( e . width ) , i . removeChild ( t ) } } ( ) , "string" == typeof t && ( t = document . querySelector ( t ) ) , t && "object" == typeof t && t . nodeType ) { var i = E ( t ) ; if ( "none" == i . display ) return function ( ) { for ( var t = { width : 0 , height : 0 , innerWidth : 0 , innerHeight : 0 , outerWidth : 0 , outerHeight : 0 } , i = 0 ; i < b ; i ++ ) t [ y [ i ] ] = 0 ; return t } ( ) ; var e = { } ; e . width = t . offsetWidth , e . height = t . offsetHeight ; for ( var n = e . isBorderBox = "border-box" == i . boxSizing , o = 0 ; o < b ; o ++ ) { var r = y [ o ] , s = i [ r ] , h = parseFloat ( s ) ; e [ r ] = isNaN ( h ) ? 0 : h } var a = e . paddingLeft + e . paddingRight , d = e . paddingTop + e . paddingBottom , u = e . marginLeft + e . marginRight , c = e . marginTop + e . marginBottom , p = e . borderLeftWidth + e . borderRightWidth , f = e . borderTopWidth + e . borderBottomWidth , g = n && _ , l = m ( i . width ) ; ! 1 !== l && ( e . width = l + ( g ? 0 : a + p ) ) ; var v = m ( i . height ) ; return ! 1 !== v && ( e . height = v + ( g ? 0 : d + f ) ) , e . innerWidth = e . width - ( a + p ) , e . innerHeight = e . height - ( d + f ) , e . outerWidth = e . width + u , e . outerHeight = e . height + c , e } } return P } ) , function ( t , i ) { "function" == typeof define && define . amd ? define ( "ev-emitter/ev-emitter" , i ) : "object" == typeof module && module . exports ? module . exports = i ( ) : t . EvEmitter = i ( ) } ( "undefined" != typeof window ? window : this , function ( ) { function t ( ) { } var i = t . prototype ; return i . on = function ( t , i ) { if ( t && i ) { var e = this . _events = this . _events || { } , n = e [ t ] = e [ t ] || [ ] ; return - 1 == n . indexOf ( i ) && n . push ( i ) , this } } , i . once = function ( t , i ) { if ( t && i ) { this . on ( t , i ) ; var e = this . _onceEvents = this . _onceEvents || { } ; return ( e [ t ] = e [ t ] || { } ) [ i ] = ! 0 , this } } , i . off = function ( t , i ) { var e = this . _events && this . _events [ t ] ; if ( e && e . length ) { var n = e . indexOf ( i ) ; return - 1 != n && e . splice ( n , 1 ) , this } } , i . emitEvent = function ( t , i ) { var e = this . _events && this . _events [ t ] ; if ( e && e . length ) { e = e . slice ( 0 ) , i = i || [ ] ; for ( var n = this . _onceEvents && this . _onceEvents [ t ] , o = 0 ; o < e . length ; o ++ ) { var r = e [ o ] ; n && n [ r ] && ( this . off ( t , r ) , delete n [ r ] ) , r . apply ( this , i ) } return this } } , i . allOff = function ( ) { delete this . _events , delete this . _onceEvents } , t } ) , function ( i , e ) { "function" == typeof define && define . amd ? define ( "unipointer/unipointer" , [ "ev-emitter/ev-emitter" ] , function ( t ) { return e ( i , t
2019-05-12 01:44:58 +08:00
const Draggabilly = window . Draggabilly ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
const TAB _CONTENT _MIN _WIDTH = 24 ;
const TAB _CONTENT _MAX _WIDTH = 240 ;
2019-05-12 16:59:53 +08:00
const NEW _TAB _WIDTH = 32 ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
const TAB _SIZE _SMALL = 84 ;
const TAB _SIZE _SMALLER = 60 ;
const TAB _SIZE _MINI = 48 ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
const tabTemplate = `
< div class = "note-tab" >
< div class = "note-tab-wrapper" >
< div class = "note-tab-title" > < / d i v >
< div class = "note-tab-drag-handle" > < / d i v >
< div class = "note-tab-close" > < span > × < / s p a n > < / d i v >
< / d i v >
2019-05-12 16:11:41 +08:00
< / d i v > ` ;
2019-05-12 01:44:58 +08:00
2019-05-12 16:59:53 +08:00
const newTabButtonTemplate = ` <div class="note-new-tab" title="Add new tab">+</div> ` ;
2019-05-12 01:44:58 +08:00
class TabRow {
2019-05-13 03:45:30 +08:00
constructor ( el ) {
2019-05-12 03:27:27 +08:00
this . draggabillies = [ ] ;
this . eventListeners = { } ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
this . el = el ;
2019-05-13 03:45:30 +08:00
this . hideTabRowForOneTab = false ;
2019-05-12 01:44:58 +08:00
this . setupStyleEl ( ) ;
this . setupEvents ( ) ;
this . layoutTabs ( ) ;
this . setupDraggabilly ( ) ;
2019-05-12 16:59:53 +08:00
this . setupNewButton ( ) ;
2019-05-12 01:44:58 +08:00
this . setVisibility ( ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-12 03:27:27 +08:00
addListener ( eventName , callback ) {
this . eventListeners [ eventName ] = this . eventListeners [ eventName ] || [ ] ;
this . eventListeners [ eventName ] . push ( callback ) ;
}
async emit ( eventName , data ) {
for ( const listener of this . eventListeners [ eventName ] ) {
await listener ( { detail : data } ) ;
}
2019-05-01 04:31:12 +08:00
}
2019-05-13 03:45:30 +08:00
setHideTabRowForOneTab ( hideTabRowForOneTab ) {
this . hideTabRowForOneTab = hideTabRowForOneTab ;
this . setVisibility ( ) ;
}
2019-05-01 04:31:12 +08:00
setupStyleEl ( ) {
2019-05-12 01:44:58 +08:00
this . styleEl = document . createElement ( 'style' ) ;
this . el . appendChild ( this . styleEl ) ;
2019-05-01 04:31:12 +08:00
}
setupEvents ( ) {
2019-05-12 01:44:58 +08:00
window . addEventListener ( 'resize' , _ => {
this . cleanUpPreviouslyDraggedTabs ( ) ;
this . layoutTabs ( ) ;
} ) ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
this . tabEls . forEach ( ( tabEl ) => this . setTabCloseEventListener ( tabEl ) ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-08 04:14:35 +08:00
setVisibility ( ) {
2019-05-13 03:45:30 +08:00
this . el . style . display = ( this . tabEls . length > 1 || ! this . hideTabRowForOneTab ) ? "block" : "none" ;
2019-05-08 04:14:35 +08:00
}
2019-05-01 04:31:12 +08:00
get tabEls ( ) {
2019-05-12 01:44:58 +08:00
return Array . prototype . slice . call ( this . el . querySelectorAll ( '.note-tab' ) ) ;
2019-05-01 04:31:12 +08:00
}
get tabContentEl ( ) {
2019-05-12 01:44:58 +08:00
return this . el . querySelector ( '.note-tab-row-content' ) ;
2019-05-01 04:31:12 +08:00
}
get tabContentWidths ( ) {
2019-05-12 01:44:58 +08:00
const numberOfTabs = this . tabEls . length ;
2019-05-12 16:59:53 +08:00
const tabsContentWidth = this . tabContentEl . clientWidth - NEW _TAB _WIDTH ;
2019-05-12 16:21:27 +08:00
const targetWidth = tabsContentWidth / numberOfTabs ;
2019-05-12 01:44:58 +08:00
const clampedTargetWidth = Math . max ( TAB _CONTENT _MIN _WIDTH , Math . min ( TAB _CONTENT _MAX _WIDTH , targetWidth ) ) ;
const flooredClampedTargetWidth = Math . floor ( clampedTargetWidth ) ;
2019-05-12 16:21:27 +08:00
const totalTabsWidthUsingTarget = flooredClampedTargetWidth * numberOfTabs ;
2019-05-12 01:44:58 +08:00
const totalExtraWidthDueToFlooring = tabsContentWidth - totalTabsWidthUsingTarget ;
const widths = [ ] ;
let extraWidthRemaining = totalExtraWidthDueToFlooring ;
for ( let i = 0 ; i < numberOfTabs ; i += 1 ) {
const extraWidth = flooredClampedTargetWidth < TAB _CONTENT _MAX _WIDTH && extraWidthRemaining > 0 ? 1 : 0 ;
widths . push ( flooredClampedTargetWidth + extraWidth ) ;
if ( extraWidthRemaining > 0 ) extraWidthRemaining -= 1 ;
}
2019-05-01 04:31:12 +08:00
2019-05-12 16:11:41 +08:00
return widths ;
2019-05-01 04:31:12 +08:00
}
2019-05-12 16:59:53 +08:00
getTabPositions ( ) {
const tabPositions = [ ] ;
2019-05-12 01:44:58 +08:00
const tabContentWidths = this . tabContentWidths ;
2019-05-12 16:11:41 +08:00
let position = 0 ;
2019-05-12 16:21:27 +08:00
tabContentWidths . forEach ( width => {
2019-05-12 16:59:53 +08:00
tabPositions . push ( position ) ;
2019-05-12 01:44:58 +08:00
position += width ;
} ) ;
2019-05-01 04:31:12 +08:00
2019-05-12 16:59:53 +08:00
const newTabPosition = position ;
2019-05-01 04:31:12 +08:00
2019-05-12 16:59:53 +08:00
return { tabPositions , newTabPosition } ;
2019-05-01 04:31:12 +08:00
}
layoutTabs ( ) {
2019-05-12 01:44:58 +08:00
const tabContentWidths = this . tabContentWidths ;
this . tabEls . forEach ( ( tabEl , i ) => {
2019-05-12 16:11:41 +08:00
const width = tabContentWidths [ i ] ;
2019-05-12 01:44:58 +08:00
tabEl . style . width = width + 'px' ;
tabEl . removeAttribute ( 'is-small' ) ;
tabEl . removeAttribute ( 'is-smaller' ) ;
tabEl . removeAttribute ( 'is-mini' ) ;
2019-05-12 16:11:41 +08:00
if ( width < TAB _SIZE _SMALL ) tabEl . setAttribute ( 'is-small' , '' ) ;
if ( width < TAB _SIZE _SMALLER ) tabEl . setAttribute ( 'is-smaller' , '' ) ;
if ( width < TAB _SIZE _MINI ) tabEl . setAttribute ( 'is-mini' , '' ) ;
2019-05-12 01:44:58 +08:00
} ) ;
let styleHTML = '' ;
2019-05-12 16:59:53 +08:00
const { tabPositions , newTabPosition } = this . getTabPositions ( ) ;
tabPositions . forEach ( ( position , i ) => {
2019-05-14 05:08:59 +08:00
styleHTML += ` .note-tab:nth-child( ${ i + 1 } ) { transform: translate3d( ${ position } px, 0, 0)} ` ;
2019-05-12 01:44:58 +08:00
} ) ;
2019-05-14 05:08:59 +08:00
styleHTML += ` .note-new-tab { transform: translate3d( ${ newTabPosition } px, 0, 0) } ` ;
2019-05-12 16:59:53 +08:00
2019-05-12 01:44:58 +08:00
this . styleEl . innerHTML = styleHTML ;
2019-05-01 04:31:12 +08:00
}
2019-05-15 04:29:47 +08:00
addTab ( tabId ) {
2019-05-12 01:44:58 +08:00
const div = document . createElement ( 'div' ) ;
div . innerHTML = tabTemplate ;
const tabEl = div . firstElementChild ;
2019-05-15 04:29:47 +08:00
tabEl . setAttribute ( 'data-tab-id' , tabId ) ;
2019-05-01 04:31:12 +08:00
2019-05-12 16:59:53 +08:00
tabEl . classList . add ( 'note-tab-was-just-added' ) ;
setTimeout ( ( ) => tabEl . classList . remove ( 'note-tab-was-just-added' ) , 500 ) ;
2019-05-01 04:31:12 +08:00
2019-05-12 18:58:55 +08:00
this . newTabEl . before ( tabEl ) ;
2019-05-12 01:44:58 +08:00
this . setVisibility ( ) ;
this . setTabCloseEventListener ( tabEl ) ;
2019-05-15 04:29:47 +08:00
this . updateTab ( tabEl , { title : 'New tab' } ) ;
2019-05-12 01:44:58 +08:00
this . cleanUpPreviouslyDraggedTabs ( ) ;
this . layoutTabs ( ) ;
this . setupDraggabilly ( ) ;
return tabEl ;
2019-05-01 04:31:12 +08:00
}
setTabCloseEventListener ( tabEl ) {
2019-05-12 01:44:58 +08:00
tabEl . querySelector ( '.note-tab-close' ) . addEventListener ( 'click' , _ => this . removeTab ( tabEl ) ) ;
2019-05-16 03:50:27 +08:00
tabEl . addEventListener ( 'mousedown' , e => {
if ( e . which === 2 ) {
this . removeTab ( tabEl ) ;
return true ; // event has been handled
}
} ) ;
2019-05-01 04:31:12 +08:00
}
get activeTabEl ( ) {
2019-05-12 01:44:58 +08:00
return this . el . querySelector ( '.note-tab[active]' ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-08 03:04:07 +08:00
get previousTabEl ( ) {
2019-05-12 01:44:58 +08:00
const tabEls = this . tabEls ;
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
if ( tabEls . length <= 1 ) {
return null ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
let prev = tabEls [ tabEls . length - 1 ] ;
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
for ( const tabEl of tabEls ) {
if ( tabEl . hasAttribute ( "active" ) ) {
return prev ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
prev = tabEl ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
return null ;
2019-05-08 03:04:07 +08:00
}
get nextTabEl ( ) {
2019-05-12 01:44:58 +08:00
const tabEls = this . tabEls ;
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
if ( tabEls . length <= 1 ) {
return null ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
let prev = tabEls [ tabEls . length - 1 ] ;
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
for ( const tabEl of tabEls ) {
if ( prev . hasAttribute ( "active" ) ) {
return tabEl ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
prev = tabEl ;
}
2019-05-08 03:04:07 +08:00
2019-05-12 01:44:58 +08:00
return null ;
2019-05-08 03:04:07 +08:00
}
2019-05-01 04:31:12 +08:00
hasActiveTab ( ) {
2019-05-12 01:44:58 +08:00
return ! ! this . activeTabEl ;
2019-05-01 04:31:12 +08:00
}
2019-05-15 04:29:47 +08:00
async activateTab ( tabEl ) {
2019-05-12 01:44:58 +08:00
const activeTabEl = this . activeTabEl ;
if ( activeTabEl === tabEl ) return ;
if ( activeTabEl ) activeTabEl . removeAttribute ( 'active' ) ;
tabEl . setAttribute ( 'active' , '' ) ;
2019-05-12 03:27:27 +08:00
await this . emit ( 'activeTabChange' , { tabEl } ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-12 03:27:27 +08:00
async removeTab ( tabEl ) {
2019-05-12 01:44:58 +08:00
if ( tabEl === this . activeTabEl ) {
2019-05-12 23:28:20 +08:00
if ( tabEl . nextElementSibling && tabEl . nextElementSibling . classList . contains ( "note-tab" ) ) {
2019-05-15 04:29:47 +08:00
await this . activateTab ( tabEl . nextElementSibling )
2019-05-12 23:28:20 +08:00
} else if ( tabEl . previousElementSibling && tabEl . previousElementSibling . classList . contains ( "note-tab" ) ) {
2019-05-15 04:29:47 +08:00
await this . activateTab ( tabEl . previousElementSibling )
2019-05-12 01:44:58 +08:00
}
2019-05-01 04:31:12 +08:00
}
2019-05-12 01:44:58 +08:00
tabEl . parentNode . removeChild ( tabEl ) ;
2019-05-12 03:27:27 +08:00
await this . emit ( 'tabRemove' , { tabEl } ) ;
2019-05-12 01:44:58 +08:00
this . cleanUpPreviouslyDraggedTabs ( ) ;
this . layoutTabs ( ) ;
this . setupDraggabilly ( ) ;
this . setVisibility ( ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-16 03:50:27 +08:00
async removeAllTabs ( ) {
for ( const tabEl of this . tabEls ) {
await this . removeTab ( tabEl ) ;
}
}
2019-05-12 03:27:27 +08:00
async removeAllTabsExceptForThis ( remainingTabEl ) {
2019-05-12 01:44:58 +08:00
for ( const tabEl of this . tabEls ) {
if ( remainingTabEl !== tabEl ) {
2019-05-12 03:27:27 +08:00
await this . removeTab ( tabEl ) ;
2019-05-12 01:44:58 +08:00
}
2019-05-08 03:34:01 +08:00
}
}
2019-05-01 04:31:12 +08:00
updateTab ( tabEl , tabProperties ) {
2019-05-12 01:44:58 +08:00
tabEl . querySelector ( '.note-tab-title' ) . textContent = tabProperties . title ;
2019-05-01 04:31:12 +08:00
}
cleanUpPreviouslyDraggedTabs ( ) {
2019-05-12 01:44:58 +08:00
this . tabEls . forEach ( ( tabEl ) => tabEl . classList . remove ( 'note-tab-was-just-dragged' ) ) ;
2019-05-01 04:31:12 +08:00
}
setupDraggabilly ( ) {
2019-05-12 01:44:58 +08:00
const tabEls = this . tabEls ;
2019-05-12 16:59:53 +08:00
const { tabPositions } = this . getTabPositions ( ) ;
2019-05-12 01:44:58 +08:00
if ( this . isDragging ) {
this . isDragging = false ;
this . el . classList . remove ( 'note-tab-row-is-sorting' ) ;
this . draggabillyDragging . element . classList . remove ( 'note-tab-is-dragging' ) ;
this . draggabillyDragging . element . style . transform = '' ;
this . draggabillyDragging . dragEnd ( ) ;
this . draggabillyDragging . isDragging = false ;
2019-05-12 03:27:27 +08:00
this . draggabillyDragging . positionDrag = _ => { } ; // Prevent Draggabilly from updating tabEl.style.transform in later frames
2019-05-12 01:44:58 +08:00
this . draggabillyDragging . destroy ( ) ;
this . draggabillyDragging = null ;
}
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
this . draggabillies . forEach ( d => d . destroy ( ) ) ;
tabEls . forEach ( ( tabEl , originalIndex ) => {
const originalTabPositionX = tabPositions [ originalIndex ] ;
const draggabilly = new Draggabilly ( tabEl , {
axis : 'x' ,
handle : '.note-tab-drag-handle' ,
containment : this . tabContentEl
} ) ;
this . draggabillies . push ( draggabilly ) ;
draggabilly . on ( 'pointerDown' , _ => {
2019-05-15 04:29:47 +08:00
this . activateTab ( tabEl )
2019-05-12 01:44:58 +08:00
} ) ;
draggabilly . on ( 'dragStart' , _ => {
this . isDragging = true ;
this . draggabillyDragging = draggabilly ;
tabEl . classList . add ( 'note-tab-is-dragging' ) ;
this . el . classList . add ( 'note-tab-row-is-sorting' ) ;
} ) ;
draggabilly . on ( 'dragEnd' , _ => {
this . isDragging = false ;
const finalTranslateX = parseFloat ( tabEl . style . left , 10 ) ;
tabEl . style . transform = ` translate3d(0, 0, 0) ` ;
// Animate dragged tab back into its place
requestAnimationFrame ( _ => {
tabEl . style . left = '0' ;
tabEl . style . transform = ` translate3d( ${ finalTranslateX } px, 0, 0) ` ;
requestAnimationFrame ( _ => {
tabEl . classList . remove ( 'note-tab-is-dragging' ) ;
this . el . classList . remove ( 'note-tab-row-is-sorting' ) ;
tabEl . classList . add ( 'note-tab-was-just-dragged' ) ;
requestAnimationFrame ( _ => {
tabEl . style . transform = '' ;
this . layoutTabs ( ) ;
this . setupDraggabilly ( ) ;
} )
} )
} )
} ) ;
draggabilly . on ( 'dragMove' , ( event , pointer , moveVector ) => {
// Current index be computed within the event since it can change during the dragMove
const tabEls = this . tabEls ;
const currentIndex = tabEls . indexOf ( tabEl ) ;
const currentTabPositionX = originalTabPositionX + moveVector . x ;
2019-05-12 16:59:53 +08:00
const destinationIndexTarget = this . closest ( currentTabPositionX , tabPositions ) ;
2019-05-12 01:44:58 +08:00
const destinationIndex = Math . max ( 0 , Math . min ( tabEls . length , destinationIndexTarget ) ) ;
if ( currentIndex !== destinationIndex ) {
this . animateTabMove ( tabEl , currentIndex , destinationIndex ) ;
}
2019-05-01 04:31:12 +08:00
} )
} )
}
2019-05-12 03:27:27 +08:00
async animateTabMove ( tabEl , originIndex , destinationIndex ) {
2019-05-12 01:44:58 +08:00
if ( destinationIndex < originIndex ) {
tabEl . parentNode . insertBefore ( tabEl , this . tabEls [ destinationIndex ] ) ;
} else {
2019-05-23 03:59:14 +08:00
const beforeEl = this . tabEls [ destinationIndex + 1 ] || this . newTabEl ;
tabEl . parentNode . insertBefore ( tabEl , beforeEl ) ;
2019-05-12 01:44:58 +08:00
}
2019-05-12 03:27:27 +08:00
await this . emit ( 'tabReorder' , { tabEl , originIndex , destinationIndex } ) ;
2019-05-12 01:44:58 +08:00
this . layoutTabs ( ) ;
2019-05-01 04:31:12 +08:00
}
2019-05-12 16:59:53 +08:00
setupNewButton ( ) {
const div = document . createElement ( 'div' ) ;
div . innerHTML = newTabButtonTemplate ;
this . newTabEl = div . firstElementChild ;
this . tabContentEl . appendChild ( this . newTabEl ) ;
this . layoutTabs ( ) ;
2019-05-12 18:58:55 +08:00
this . newTabEl . addEventListener ( 'click' , _ => this . emit ( 'newTab' ) ) ;
2019-05-12 16:59:53 +08:00
}
closest ( value , array ) {
let closest = Infinity ;
let closestIndex = - 1 ;
array . forEach ( ( v , i ) => {
if ( Math . abs ( value - v ) < closest ) {
closest = Math . abs ( value - v ) ;
closestIndex = i
}
} ) ;
return closestIndex ;
} ;
2019-05-12 01:44:58 +08:00
}
const noteTabRowEl = document . querySelector ( '.note-tab-row' ) ;
2019-05-13 03:45:30 +08:00
const tabRow = new TabRow ( noteTabRowEl ) ;
optionsInit . addLoadListener ( options => tabRow . setHideTabRowForOneTab ( options . hideTabRowForOneTab === 'true' ) ) ;
2019-05-01 04:31:12 +08:00
2019-05-12 01:44:58 +08:00
export default tabRow ;