import emitter from '../lib/emitter' import Settings from '../Settings/Settings' import Emitter from 'licia/Emitter' import $ from 'licia/$' import nextTick from 'licia/nextTick' import orientation from 'licia/orientation' import pointerEvent from 'licia/pointerEvent' import { pxToNum, classPrefix as c, eventClient } from '../lib/util' import evalCss from '../lib/evalCss' const $document = $(document) export default class EntryBtn extends Emitter { constructor($container) { super() this._style = evalCss(require('./EntryBtn.scss')) this._$container = $container this._initTpl() this._bindEvent() this._registerListener() } hide() { this._$el.hide() } show() { this._$el.show() } setPos(pos) { if (this._isOutOfRange(pos)) { pos = this._getDefPos() } this._$el.css({ left: pos.x, top: pos.y, }) this.config.set('pos', pos) } getPos() { return this.config.get('pos') } destroy() { evalCss.remove(this._style) this._unregisterListener() this._$el.remove() } _isOutOfRange(pos) { pos = pos || this.config.get('pos') const defPos = this._getDefPos() return ( pos.x > defPos.x + 10 || pos.x < 0 || pos.y < 0 || pos.y > defPos.y + 10 ) } _registerListener() { this._scaleListener = () => nextTick(() => { if (this._isOutOfRange()) this._resetPos() }) emitter.on(emitter.SCALE, this._scaleListener) } _unregisterListener() { emitter.off(emitter.SCALE, this._scaleListener) } _initTpl() { const $container = this._$container $container.append( c('
') ) this._$el = $container.find('.eruda-entry-btn') } _resetPos(orientationChanged) { const cfg = this.config let pos = cfg.get('pos') const defPos = this._getDefPos() if (!cfg.get('rememberPos') || orientationChanged) { pos = defPos } this.setPos(pos) } _onDragStart = (e) => { const $el = this._$el $el.addClass(c('active')) this._isClick = true e = e.origEvent this._startX = eventClient('x', e) this._oldX = pxToNum($el.css('left')) this._oldY = pxToNum($el.css('top')) this._startY = eventClient('y', e) $document.on(pointerEvent('move'), this._onDragMove) $document.on(pointerEvent('up'), this._onDragEnd) } _onDragMove = (e) => { const btnSize = this._$el.get(0).offsetWidth const maxWidth = this._$container.get(0).offsetWidth const maxHeight = this._$container.get(0).offsetHeight e = e.origEvent const deltaX = eventClient('x', e) - this._startX const deltaY = eventClient('y', e) - this._startY if (Math.abs(deltaX) > 3 || Math.abs(deltaY) > 3) { this._isClick = false } let newX = this._oldX + deltaX let newY = this._oldY + deltaY if (newX < 0) { newX = 0 } else if (newX > maxWidth - btnSize) { newX = maxWidth - btnSize } if (newY < 0) { newY = 0 } else if (newY > maxHeight - btnSize) { newY = maxHeight - btnSize } this._$el.css({ left: newX, top: newY, }) } _onDragEnd = (e) => { const $el = this._$el if (this._isClick) { this.emit('click') } this._onDragMove(e) $document.off(pointerEvent('move'), this._onDragMove) $document.off(pointerEvent('up'), this._onDragEnd) const cfg = this.config if (cfg.get('rememberPos')) { cfg.set('pos', { x: pxToNum($el.css('left')), y: pxToNum($el.css('top')), }) } $el.rmClass('eruda-active') } _bindEvent() { const $el = this._$el $el.on(pointerEvent('down'), this._onDragStart) orientation.on('change', () => this._resetPos(true)) window.addEventListener('resize', () => this._resetPos()) } initCfg(settings) { const cfg = (this.config = Settings.createCfg('entry-button', { rememberPos: true, pos: this._getDefPos(), })) settings.switch(cfg, 'rememberPos', '入力ボタンの位置を記憶する') this._resetPos() } _getDefPos() { const minWidth = this._$el.get(0).offsetWidth + 10 return { x: window.innerWidth - minWidth, y: window.innerHeight - minWidth, } } }