Skip to content

Instantly share code, notes, and snippets.

@jmsfwk
Last active February 28, 2018 14:59
Show Gist options
  • Save jmsfwk/ec74b4c3ff8c23ea5d0c78dfa378054f to your computer and use it in GitHub Desktop.
Save jmsfwk/ec74b4c3ff8c23ea5d0c78dfa378054f to your computer and use it in GitHub Desktop.
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
<script>
const data = [
{
"id": "739d8b36-e80f-4c04-9188-757a5bd64e70",
"headline": "Liverpool initiative for renewing housing stock to benefit local contractors"
},
{
"id": "739e5179-80ba-435a-9b92-bd3e77fc78a0",
"headline": "UK Budget: portfolio impact muted"
},
{
"id": "739f0851-416d-4fef-be25-953a1726aa0e",
"headline": "ProAxia Consulting Group | AeroOne®"
},
{
"id": "73a681c9-e032-4dca-8c20-96f7d538a8a5",
"headline": "World first for ACCA and University of London"
},
{
"id": "73a6b00d-1f48-4e6b-9bd2-c38a509c2975",
"headline": "Student IT experience at The Arthur Terry Learning Partnership is transformed by Hybrid Cloud "
},
{
"id": "739f0b60-7a0f-4d16-b288-f7647b4a8a6a",
"headline": "Latimer Hinks Warns Businesses Over Insurance Obligations"
},
{
"id": "739fb078-e840-4afe-b293-2af0e78370eb",
"headline": "Butchery acquisition leads to an additional £4m increase in turnover for Harlech Foodservice"
},
{
"id": "73a0f61d-3478-4e94-9c1d-f6bb7dec4543",
"headline": "Leeds’ Samuel Grant Group take home gold"
},
{
"id": "73a15ea7-8e56-4d39-a780-76cb6400fbda",
"headline": "Access Programme marks a year of exporting success for North East businesses"
},
{
"id": "73a265e3-5e7a-4512-9ada-02bb56a97a28",
"headline": "Balancing the benefits of BYOD"
}
];
</script>
<style>
li.focused {
outline: 1px dotted black;
}
li[aria-selected=true] {
color: red;
}
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/x-template" id="template">
<ul role="listbox" tabindex="0" aria-multiselectable="true"
:aria-activedescendant="activedescendant"
@keydown.a="ctrlA"
@keydown.35="end"
@keydown.36="home"
@keydown.up="up"
@keydown.down="down"
@keydown.space="space">
<li v-for="(option, i) in options" role="option"
:key="i"
:id="`${id}_${i}`"
:class="{focused: isFocused(i)}"
:aria-selected="isSelected(i)"
@click="click(i)">{{ option.headline }}</li>
</ul>
</script>
<script>
const app = new Vue({
el: '#app',
template: '#template',
data: {
id: '',
checked: [],
focused: null,
selected: null,
lastSelected: null,
options: data,
},
computed: {
activedescendant() {
return this.focused !== null ? `${this.id}_${this.focused}` : false;
},
max() {
return this.options.length - 1;
}
},
methods: {
isChecked(i) {
return this.checked.includes(i);
},
isFocused(i) {
return i === this.focused;
},
isSelected(i) {
return this.checked.includes(i);
},
ctrlA(e){
if (e.ctrlKey) {
for (const i of this.options.keys()) {
if (!this.isChecked(i)) {
this.check(i);
}
}
}
},
home(e) {
console.log(e);
this.focus(0);
},
end(e) {
console.log(e);
this.focus(this.max);
},
up(e) {
console.log(e);
this.focus(this.focused - 1);
},
down(e) {
console.log(e);
this.focus(this.focused + 1);
if (e.shiftKey) {
this.select(this.focused);
}
},
selectContiguous(_start, _end) {
const start = Math.min(_start, _end);
const end = Math.max(_start, _end);
console.log(start, end);
for (let i = start; i <= end; i++) {
this.select(i);
}
},
space(e) {
if (e.shiftKey) {
this.selectContiguous(this.focused, this.lastSelected);
return;
}
if (null !== this.focused) {
this.toggle(this.focused);
}
},
click(i) {
this.focus(i);
this.toggle(i);
},
focus(i) {
if(i <= this.max && i >= 0) {
this.focused = i;
}
},
select(i) {
if(!this.isSelected(i)) {
const index = this.checked.indexOf(null);
Vue.set(this.checked, index === -1 ? this.checked.length : index, i);
this.lastSelected = i;
}
},
unselect(i) {
const index = this.checked.indexOf(i);
Vue.set(this.checked, index, null);
},
toggle(i) {
if(!this.isSelected(i)) {
this.select(i);
} else {
this.unselect(i);
}
},
log(e) {
console.log(e);
},
},
created() {
console.log(this.$data);
this.id = Array.from(crypto.getRandomValues(new Uint8Array(8)))
.map(v => v.toString(16))
.map(a => a.padStart(2, '0'))
.join('');
}
});
</script>
</body>
</html>
@jmsfwk
Copy link
Author

jmsfwk commented Feb 28, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment