aboutsummaryrefslogtreecommitdiff
path: root/src/components/Tile.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/Tile.vue')
-rw-r--r--src/components/Tile.vue121
1 files changed, 73 insertions, 48 deletions
diff --git a/src/components/Tile.vue b/src/components/Tile.vue
index 7722101..f0b506e 100644
--- a/src/components/Tile.vue
+++ b/src/components/Tile.vue
@@ -15,7 +15,7 @@ export default defineComponent({
data(){
return {
nonLeafHighlight: false,
- dblClickTimer: 0, // Used to delay a click action until a double-click timeout ends
+ clickHoldTimer: 0, // Used to recognise a click-and-hold event
zIdx: 0, // Used during transitions
overflow: 'visible', // Used during transitions
}
@@ -121,58 +121,69 @@ export default defineComponent({
},
},
methods: {
- // For click handling
- onLeafClick(evt: UIEvent){
+ // Leaf click handling
+ onLeafMouseDown(){
+ clearTimeout(this.clickHoldTimer);
+ this.clickHoldTimer = setTimeout(() => {
+ this.clickHoldTimer = 0;
+ this.onLeafClickHold();
+ }, this.options.clickHoldDuration);
+ },
+ onLeafMouseUp(){
+ if (this.clickHoldTimer > 0){
+ clearTimeout(this.clickHoldTimer);
+ this.clickHoldTimer = 0;
+ this.onLeafClick();
+ }
+ },
+ onLeafClick(){
if (!this.isExpandable){
- console.log('Ignored click on non-expandable leaf node');
+ console.log('Ignored click on non-expandable node');
return;
}
- let prepForTransition = () => {
- // Temporary changes to prevent content overlap and overflow
- this.zIdx = 1;
- this.overflow = 'hidden';
- setTimeout(() => {this.zIdx = 0; this.overflow = 'visible';}, this.options.transitionDuration);
- };
- if (evt.detail == 1){
- this.dblClickTimer = setTimeout(() => {
- this.$emit('leaf-clicked', {layoutNode: this.layoutNode, domNode: this.$el});
- prepForTransition();
- }, this.options.dblClickWait);
- } else if (evt.detail == 2){
- clearTimeout(this.dblClickTimer);
- this.$emit('leaf-dbl-clicked', this.layoutNode);
- prepForTransition();
+ this.$emit('leaf-clicked', {layoutNode: this.layoutNode, domNode: this.$el});
+ this.leafPrepTransition();
+ },
+ onLeafClickHold(){
+ if (!this.isExpandable){
+ console.log('Ignored click-hold on non-expandable node');
+ return;
}
+ this.$emit('leaf-click-held', this.layoutNode);
+ this.leafPrepTransition();
},
- onInnerLeafClicked(data: {layoutNode: LayoutNode, domNode: HTMLElement}){
- this.$emit('leaf-clicked', data);
+ leafPrepTransition(){ // Temporary style changes to prevent content overlap and overflow
+ this.zIdx = 1;
+ this.overflow = 'hidden';
+ setTimeout(() => {this.zIdx = 0; this.overflow = 'visible';}, this.options.transitionDuration);
},
- onHeaderClick(evt: UIEvent){
+ // Non-leaf click handling
+ onHeaderMouseDown(){
this.nonLeafHighlight = false;
- let prepForTransition = () => {
- // Temporary changes to prevent content overlap and overflow
- this.zIdx = 1;
- setTimeout(() => {this.zIdx = 0}, this.options.transitionDuration);
- };
- if (evt.detail == 1){
- this.dblClickTimer = setTimeout(() => {
- this.$emit('header-clicked', {layoutNode: this.layoutNode, domNode: this.$el});
- prepForTransition();
- }, this.options.dblClickWait);
- } else if (evt.detail == 2){
- clearTimeout(this.dblClickTimer);
- this.$emit('header-dbl-clicked', this.layoutNode);
- prepForTransition();
+ clearTimeout(this.clickHoldTimer);
+ this.clickHoldTimer = setTimeout(() => {
+ this.clickHoldTimer = 0;
+ this.onHeaderClickHold();
+ }, this.options.clickHoldDuration);
+ },
+ onHeaderMouseUp(){
+ if (this.clickHoldTimer > 0){
+ clearTimeout(this.clickHoldTimer);
+ this.clickHoldTimer = 0;
+ this.onHeaderClick();
}
},
- onInnerHeaderClicked(data: {layoutNode: LayoutNode, domNode: HTMLElement}){
- this.$emit('header-clicked', data);
+ onHeaderClick(){
+ this.$emit('header-clicked', {layoutNode: this.layoutNode, domNode: this.$el});
+ this.nonLeafPrepForTransition();
},
- onInnerLeafDblClicked(data: LayoutNode){
- this.$emit('leaf-dbl-clicked', data);
+ onHeaderClickHold(){
+ this.$emit('header-click-held', this.layoutNode);
+ this.nonLeafPrepForTransition();
},
- onInnerHeaderDblClicked(data: LayoutNode){
- this.$emit('header-dbl-clicked', data);
+ nonLeafPrepForTransition(){ // Temporary style changes to prevent content overlap and overflow
+ this.zIdx = 1;
+ setTimeout(() => {this.zIdx = 0}, this.options.transitionDuration);
},
// For coloured-outlines on hovered-over leaf-tiles or non-leaf-headers
onNonLeafMouseEnter(evt: Event){
@@ -181,7 +192,19 @@ export default defineComponent({
onNonLeafMouseLeave(evt: Event){
this.nonLeafHighlight = false;
},
- // For child event propagation
+ // Child event propagation
+ onInnerLeafClicked(data: {layoutNode: LayoutNode, domNode: HTMLElement}){
+ this.$emit('leaf-clicked', data);
+ },
+ onInnerHeaderClicked(data: {layoutNode: LayoutNode, domNode: HTMLElement}){
+ this.$emit('header-clicked', data);
+ },
+ onInnerLeafClickHeld(data: LayoutNode){
+ this.$emit('leaf-click-held', data);
+ },
+ onInnerHeaderClickHeld(data: LayoutNode){
+ this.$emit('header-click-held', data);
+ },
onInnerInfoIconClicked(data: LayoutNode){
this.$emit('info-icon-clicked', data);
}
@@ -190,31 +213,33 @@ export default defineComponent({
components: {
TileImg,
},
- emits: ['leaf-clicked', 'header-clicked', 'leaf-dbl-clicked', 'header-dbl-clicked', 'info-icon-clicked'],
+ emits: ['leaf-clicked', 'header-clicked', 'leaf-click-held', 'header-click-held', 'info-icon-clicked'],
});
</script>
<template>
<div :style="tileStyles">
<tile-img v-if="isLeaf" :layoutNode="layoutNode" :tileSz="layoutNode.dims[0]" :options="options"
- @click="onLeafClick" @info-icon-clicked="onInnerInfoIconClicked"/>
+ @mousedown="onLeafMouseDown" @mouseup="onLeafMouseUp" @info-icon-clicked="onInnerInfoIconClicked"/>
<div v-else :style="nonLeafStyles" ref="nonLeaf">
<h1 v-if="showHeader" :style="nonLeafHeaderStyles" class="hover:cursor-pointer"
- @click="onHeaderClick($event)" @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave">
+ @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave"
+ @mousedown="onHeaderMouseDown" @mouseup="onHeaderMouseUp">
{{layoutNode.tolNode.name}}
</h1>
<div :style="sepSweptAreaStyles" ref="sepSweptArea"
:class="layoutNode?.sepSweptArea?.sweptLeft ? 'hide-right-edge' : 'hide-top-edge'">
<h1 v-if="layoutNode?.sepSweptArea?.sweptLeft === false"
:style="nonLeafHeaderStyles" class="hover:cursor-pointer"
- @click="onHeaderClick($event)" @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave">
+ @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave"
+ @mousedown="onHeaderMouseDown" @mouseup="onHeaderMouseUp">
{{layoutNode.tolNode.name}}
</h1>
</div>
<tile v-for="child in layoutNode.children" :key="child.tolNode.name" :layoutNode="child"
:headerSz="headerSz" :tileSpacing="tileSpacing" :options="options"
@leaf-clicked="onInnerLeafClicked" @header-clicked="onInnerHeaderClicked"
- @leaf-dbl-clicked="onInnerLeafDblClicked" @header-dbl-clicked="onInnerHeaderDblClicked"
+ @leaf-click-held="onInnerLeafClickHeld" @header-click-held="onInnerHeaderClickHeld"
@info-icon-clicked="onInnerInfoIconClicked"/>
</div>
</div>