Skip to content

Commit

Permalink
feat: key nav
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhkelley1 committed Jul 17, 2022
1 parent 65e10b8 commit ae5bb24
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 19 deletions.
178 changes: 178 additions & 0 deletions check_run/public/js/check_run/ADropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<template>
<div class="autocomplete" :class="{ 'isOpen': state.transactions[transactionIndex].mopIsOpen }">
<input
type="text"
:id="`mop-input-${transactionIndex}`"
@input="onChange"
@focus="onChange"
v-model="search"
@keydown.down="onArrowDown"
@keydown.up="onArrowUp"
@keydown.enter="onEnter"
class="form-control"
/>
<ul
id="autocomplete-results"
v-show="state.transactions[transactionIndex].mopIsOpen"
class="autocomplete-results"
>
<li
class="loading"
v-if="isLoading"
>
Loading results...
</li>
<li
v-else
v-for="(result, i) in results"
:key="i"
@click="setResult(result)"
class="autocomplete-result"
:class="{ 'is-active': i === arrowCounter }"
>
{{ result }}
</li>
</ul>
</div>
</template>

<script>
export default {
name: 'ADropdown',
props: {
value: String,
//isOpen: Object,
items: {
type: Array,
required: false,
default: () => [],
},
isAsync: {
type: Boolean,
required: false,
default: false,
},
state: {
required: false
},
transactionIndex: Number
},
data() {
return {
results: [],
search: this.value,
isLoading: false,
arrowCounter: 0,
};
},
watch: {
items: function (value, oldValue) {
if (value.length !== oldValue.length) {
this.results = value;
this.isLoading = false;
}
},
value: function (value, oldValue) {
if (value !== oldValue) {
this.setResult(value)
}
}
},
mounted() {
document.addEventListener('click', this.handleClickOutside)
this.filterResults()
},
destroyed() {
document.removeEventListener('click', this.handleClickOutside)
},
methods: {
setResult(result) {
this.search = result;
this.closeResults()
},
filterResults() {
this.results = this.items.filter((item) => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
},
onChange() {
//this.$emit('input', this.search);
if (this.isAsync) {
this.isLoading = true;
} else {
this.filterResults();
this.state.transactions[this.transactionIndex].mopIsOpen = true
//this.$emit('isOpenChanged', this.isOpen.val)
}
},
handleClickOutside(event) {
if (!this.$el.contains(event.target)) {
this.closeResults()
this.arrowCounter = 0;
}
},
closeResults() {
this.state.transactions[this.transactionIndex].mopIsOpen = false
//this.$emit('isOpenChanged', this.isOpen.val)
if(!this.items.includes(this.search)) {
this.search = ''
}
if(this.value != this.search) {
cur_frm.dirty();
}
this.value = this.search
this.$emit('input', this.value)
},
onArrowDown() {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
this.search = this.results[this.arrowCounter];
this.closeResults()
this.arrowCounter = 0;
},
},
};
</script>

<style>
.autocomplete {
position: relative;
}
.autocomplete-results {
padding: 0;
margin: 0;
border: 1px solid #eeeeee;
background-color: #f4f5f6;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.autocomplete-result {
list-style: none;
text-align: left;
padding: 4px 6px;
cursor: pointer;
}
.autocomplete-result.is-active,
.autocomplete-result:hover {
background-color: #4590e8;
color: white;
}
</style>
34 changes: 16 additions & 18 deletions check_run/public/js/check_run/CheckRun.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
v-if="partyIsInFilter(transactions[i].party)"
:key=i
class="checkrun-row-container"
:class="{ selectedRow: state.selectedRow == i }"
tabindex="1"
@click="state.selectedRow = i"
>
<td style="text-align: left">{{ transactions[i].party }}</td>
<td>
Expand All @@ -60,23 +62,9 @@
class="mop-onclick"
:data-mop-index="i"
>
<select
v-if="state.docstatus < 1"
class="mop-input form-control"
:data-mop="transactions[i].mode_of_payment"
v-model="transactions[i].mode_of_payment"
@change="markDirty()"
>
<option></option>
<template v-for="(mop, j) in modes_of_payment">
<option
:value="modes_of_payment[j].name"
:key="j"
>
{{modes_of_payment[j].name}}
</option>
</template>
</select>

<ADropdown v-model="state.transactions[i].mode_of_payment" :items="modeOfPaymentNames" v-if="state.docstatus < 1" :state="state" :transactionIndex="i" />

<span v-else>{{ transactions[i].mode_of_payment }}</span>
</td>
<td>{{ format_currency(transactions[i].amount, "USD", 2) }}</td>
Expand All @@ -102,8 +90,13 @@
</template>
<script>
import ADropdown from "./ADropdown.vue";
export default {
name: 'CheckRun',
components: {
ADropdown
},
props: ['transactions', 'modes_of_payment', 'docstatus', 'state'],
data(){
return {
Expand All @@ -113,7 +106,8 @@ export default {
mode_of_payment: 1,
amount: 1,
due_date: 1
}
},
modeOfPaymentNames: this.modes_of_payment.map(mop => mop.name)
}
},
watch: {
Expand Down Expand Up @@ -170,4 +164,8 @@ export default {
.table thead th {
vertical-align: top;
}
.table tr.selectedRow {
background-color: #ececec;
}
</style>
45 changes: 44 additions & 1 deletion check_run/public/js/check_run/check_run.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import CheckRun from './CheckRun.vue'
import ADropdown from './ADropdown.vue'

frappe.provide('check_run')

check_run.mount_table = frm => {
check_run.frm = frm
frm.transactions.forEach(val => {
val.mopIsOpen = false
})
frm.check_run_state = Vue.observable({
transactions: frm.transactions,
party_filter: "",
Expand All @@ -13,7 +18,9 @@ check_run.mount_table = frm => {
return this.transactions.reduce((partialSum, t) => {
return t.pay ? partialSum + t.amount : partialSum;
}, 0);
}
},
selectedRow: 0,
mopsOpen: 0
})
if (frm.$check_run instanceof Vue) {
frm.$check_run.$destroy();
Expand All @@ -33,5 +40,41 @@ check_run.mount_table = frm => {
})
})

}

check_run.keyDownHandler = e => {
if(!check_run.frm) {
return
}

if(e.keyCode == 40 && check_run.frm.check_run_state.selectedRow < (check_run.frm.check_run_state.transactions.length - 1)){
console.log("state", check_run.frm.check_run_state)
for(let j=0;j<check_run.frm.check_run_state.transactions.length;j++) {
if(check_run.frm.check_run_state.transactions[j].mopIsOpen) {
return
}
}
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).blur()
check_run.frm.check_run_state.selectedRow += 1
}

if(e.keyCode == 38 && check_run.frm.check_run_state.selectedRow > 0){
for(let j=0;j<check_run.frm.check_run_state.transactions.length;j++) {
if(check_run.frm.check_run_state.transactions[j].mopIsOpen) {
return
}
}
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).blur()
check_run.frm.check_run_state.selectedRow -= 1
}

if(e.keyCode == 32 && check_run.frm.check_run_state.selectedRow != null && check_run.frm.check_run_state.transactions.length){
e.preventDefault()
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).focus()

}

}

window.removeEventListener('keydown', check_run.keyDownHandler);
window.addEventListener('keydown', check_run.keyDownHandler);

0 comments on commit ae5bb24

Please sign in to comment.