Files
mixly3/common/modules/web-modules/chrome-tabs.js

205 lines
5.3 KiB
JavaScript

((window, factory) => {
if (typeof define == 'function' && define.amd) {
define([], () => factory(window))
} else if (typeof module == 'object' && module.exports) {
module.exports = factory(window)
} else {
window.ChromeTabs = factory(window)
}
})(window, (window) => {
const TAB_CONTENT_MARGIN = 0
const TAB_CONTENT_OVERLAP_DISTANCE = 1
const TAB_OVERLAP_DISTANCE = (TAB_CONTENT_MARGIN * 2) + TAB_CONTENT_OVERLAP_DISTANCE
const TAB_CONTENT_MIN_WIDTH = 140
const TAB_CONTENT_MAX_WIDTH = 160
const TAB_SIZE_SMALL = 84
const TAB_SIZE_SMALLER = 60
const TAB_SIZE_MINI = 48
const noop = _ => {}
const 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
}
const tabTemplate = `
<div class="chrome-tab">
<div class="chrome-tab-dividers"></div>
<div class="chrome-tab-background"></div>
<div class="chrome-tab-content">
<div class="chrome-tab-favicon" hidden></div>
<div class="chrome-tab-title"></div>
<div class="chrome-tab-drag-handle"></div>
<div class="chrome-tab-close"></div>
</div>
</div>
`
const defaultTapProperties = {
name: 'New tab',
title: 'New tab',
favicon: false
}
let instanceId = 0
class ChromeTabs {
constructor() {
}
init(el) {
this.el = el
this.instanceId = instanceId
this.el.setAttribute('data-chrome-tabs-instance-id', this.instanceId)
instanceId += 1
this.setupCustomProperties()
$(this.el).on('click touchend', '.chrome-tab', (event) => {
if (event.type === 'touchend') {
event.preventDefault()
}
this.setCurrentTab(event.currentTarget)
})
$(this.el).on('click touchend', '.chrome-tab-close', (event) => {
event.stopPropagation()
if (event.type === 'touchend') {
event.preventDefault()
}
const $tab = $(event.currentTarget).closest('.chrome-tab')
if (!this.checkDestroy({ detail: { tabEl: $tab[0] } })) {
return
}
this.removeTab($tab[0])
})
}
emit(eventName, data) {
this.el.dispatchEvent(new CustomEvent(eventName, { detail: data }))
}
setupCustomProperties() {
this.el.style.setProperty('--tab-content-margin', `${ TAB_CONTENT_MARGIN }px`)
}
setupStyleEl() {
this.styleEl = document.createElement('style')
this.el.appendChild(this.styleEl)
}
get tabContentEl() {
return this.el.querySelector('.x-scrollbar__content') ?? this.el.querySelector('.chrome-tabs-content')
}
createNewTabEl() {
const div = document.createElement('div')
div.innerHTML = tabTemplate
return div.firstElementChild
}
addTab(tabProperties, { animate = false, background = false } = {}) {
const tabEl = this.createNewTabEl()
if (animate) {
tabEl.classList.add('chrome-tab-was-just-added')
setTimeout(() => tabEl.classList.remove('chrome-tab-was-just-added'), 500)
}
tabProperties = Object.assign({}, defaultTapProperties, tabProperties)
this.tabContentEl.appendChild(tabEl)
this.updateTab(tabEl, tabProperties)
this.emit('created', { tabEl })
if (!background) this.setCurrentTab(tabEl)
return tabEl;
}
get activeTabEl() {
return this.el.querySelector('.chrome-tab[active]')
}
hasActiveTab() {
return !!this.activeTabEl
}
setCurrentTab(tabEl) {
const activeTabEl = this.activeTabEl
if (activeTabEl === tabEl) return
if (activeTabEl) activeTabEl.removeAttribute('active')
tabEl.setAttribute('active', '')
this.emit('activeChange', { tabEl })
}
removeTab(tabEl) {
const isActive = tabEl === this.activeTabEl
let needActiveElem = null
if (isActive) {
if (tabEl.nextElementSibling) {
needActiveElem = tabEl.nextElementSibling;
} else if (tabEl.previousElementSibling) {
needActiveElem = tabEl.previousElementSibling
}
}
this.emit('beforeDestroy', { tabEl })
tabEl.parentNode.removeChild(tabEl)
this.emit('destroyed', { tabEl })
if (isActive && needActiveElem) {
this.setCurrentTab(needActiveElem)
}
}
updateTab(tabEl, tabProperties) {
if (tabProperties.name) {
tabEl.querySelector('.chrome-tab-title').textContent = tabProperties.name
}
const faviconEl = tabEl.querySelector('.chrome-tab-favicon')
if (tabProperties.favicon) {
$(faviconEl).addClass(tabProperties.favicon)
faviconEl.removeAttribute('hidden', '')
}
if (tabProperties.id) {
tabEl.setAttribute('data-tab-id', tabProperties.id)
}
if (tabProperties.title) {
tabEl.setAttribute('title', tabProperties.title)
}
if (tabProperties.type) {
tabEl.setAttribute('data-tab-type', tabProperties.type)
}
if (tabProperties.attr) {
for (let i in tabProperties.attr) {
tabEl.setAttribute(i, tabProperties.attr[i])
}
}
}
checkDestroy(event) {
return true
}
dispose() {
this.el = null;
}
}
return ChromeTabs
})