shogi-player
Version:
Shogi board web components has functions for replaying, manipulating, and editing
179 lines (147 loc) • 4.88 kB
JavaScript
import _ from "lodash"
import { Location } from "./models/location.js"
const FOCUS_FUNCTION = false
export const mod_navi = {
props: {
// 手数や結果の表示(再生モード時) (true false)
sp_turn_show: {
type: Boolean,
default: false,
},
// スライダー表示
sp_slider: {
type: Boolean,
default: false,
},
// コントローラー表示
sp_controller: {
type: Boolean,
default: false,
},
// 全体の操作を無効化
sp_operation_disabled: {
type: Boolean,
default: false,
},
// 駒がないときは駒台側を非表示
sp_piece_stand_blank_then_hidden: {
type: Boolean,
default: false,
},
// スライダーにフォーカスしていなくても左右キーで手数を動かす
sp_key_event_capture: {
type: Boolean,
default: false,
},
},
mounted() {
window.addEventListener("keydown", this.keydown_hook, false)
},
beforeDestroy() {
window.removeEventListener('keydown', this.keydown_hook)
},
methods: {
keydown_hook(e) {
if (this.debug_or_development_p) {
this.log(document.activeElement)
this.log(e.shiftKey, e.ctrlKey, e.altKey, e.metaKey)
this.log("e", e)
this.log("key", e.key)
this.log("code", e.code)
this.log("repeat", e.repeat)
}
if (this.sp_operation_disabled) {
return
}
if (this.focus_on_input_tag_p()) {
return
}
if (this.shortcut_hook(e)) {
return
}
if (this.sp_key_event_capture && (this.view_p || this.play_p)) {
const dom = document.activeElement
if (this.$NavigateBlock) {
const controllers = [
this.$NavigateBlock.$refs.first,
this.$NavigateBlock.$refs.previous,
this.$NavigateBlock.$refs.next,
this.$NavigateBlock.$refs.last,
]
if (!(dom === undefined || dom.tagName === "BODY" || _.includes(controllers, dom))) {
return
}
}
if (e.code === "Backspace" || e.code === "ArrowUp" || e.code === "ArrowLeft" || e.key === "k" || e.key === "p" || e.key === "b") {
this.api_turn_add(-1, {interactive: e})
e.preventDefault()
}
if (e.code === "Space" || e.code === "Enter" || e.code === "ArrowDown" || e.code === "ArrowRight" || e.key === "j" || e.key === "n" || e.key === "f") {
this.api_turn_add(1, {interactive: e})
e.preventDefault()
}
}
},
api_turn_add(v, options = {}) {
this.current_turn_add(v, options)
// SpSlider → (next || previous) の順でフォーカスを試みる
if (!this.turn_slider_focus()) {
// スライダーにはフォーカスできなかったのでボタンの方にフォーカスする
if (v > 0) {
this.nav_focus_to("next")
} else {
this.nav_focus_to("previous")
}
}
},
api_turn_set_to_min(options = {}) {
this.current_turn_set(this.turn_offset_min, options)
this.turn_slider_focus() || this.nav_focus_to("first")
},
api_turn_set_to_max(options = {}) {
this.current_turn_set(this.turn_offset_max, options)
this.turn_slider_focus() || this.nav_focus_to("last")
},
current_turn_add(v, options = {}) {
this.current_turn_set(this.xcontainer.turn_offset + v, options)
},
current_turn_set(v, options = {}) {
let new_val = null
if (options.cycle) {
new_val = this.xcontainer.turn_cycle(v)
} else {
new_val = this.xcontainer.turn_clamp(v)
}
const updated = this.turn_offset !== new_val
if (updated) {
this.lifted_piece_cancel() // 駒を持った状態でコントローラーを操作したとき駒を持ち上げた状態が残るのを防ぐ
if (this.view_p) {
this.view_mode_xcontainer_update(new_val)
}
if (this.play_p) {
this.play_mode_xcontainer_seek_to(new_val)
}
this.event_call("update:sp_turn", this.turn_offset)
if (options.interactive) {
this.log("局面を人が故意に変更")
this.event_call("ev_action_turn_change", this.turn_offset) // b-slider で変更
}
}
},
},
computed: {
//////////////////////////////////////////////////////////////////////////////// for NavigateBlock.vue, SpSlider.vue
inside_controller_p() {
// if (this.mut_dev_tools) {
// return true
// }
return this.sp_controller && (this.view_p || this.play_p)
},
inside_slider_p() {
return this.sp_slider && (this.view_p || this.play_p)
},
inside_navigate_p() {
return this.inside_controller_p || this.inside_slider_p
},
},
}