Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
New Twiddle
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
class Cell {
@tracked value;
constructor(key, value) {
this.key = key;
this.value = value;
}
}
function wrap(index, length) {
let wrapped = Math.abs(index) % length;
return index < 0 ? length - wrapped : wrapped;
}
function clamp(index, length) {
return Math.max(0, Math.min(index, length - 1));
}
export default class SelectList extends Component {
selectedIndexCell = new Cell(0, -1);
get selectedIndex() {
let selectedIndexCell = this.selectedIndexCell;
let length = this.items.length;
if (selectedIndexCell.key !== length) {
let clampedIndex = clamp(selectedIndexCell.value, length);
selectedIndexCell = this.selectedIndexCell = new Cell(
length,
clampedIndex
);
}
return selectedIndexCell.value;
}
set selectedIndex(value) {
this.selectedIndexCell.value = wrap(value, this.items.length);
}
get items() {
return this.args.items;
}
@action _didInsertElement() {
document.addEventListener("keydown", this.onKeydown);
}
@action _willDestroyElement() {
document.removeEventListener("keydown", this.onKeydown);
}
@action onKeydown(e) {
switch (e.key) {
case "ArrowUp":
return this.selectPrev();
case "ArrowDown":
return this.selectNext();
// case 'Enter':
// return this.didCommit();
// case 'Escape':
//. return this.didCancel();
}
}
@action selectPrev() {
this.selectedIndex--;
}
@action selectNext() {
this.selectedIndex++;
}
}
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
const ITEMS = ['one', 'two', 'three', 'four'];
export default class ApplicationController extends Controller {
@tracked items = [...ITEMS];
@action updateItems(count) {
this.items = ITEMS.slice(0, count);
}
}
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
ul {
border: 1px solid black;
}
li.selected {
background: #efefef;
}
<SelectList @items={{this.items}} />
<p>
<button {{on "click" (fn this.updateItems 1)}}>One Items</button>
<button {{on "click" (fn this.updateItems 2)}}>Two Items</button>
<button {{on "click" (fn this.updateItems 3)}}>Three Items</button>
<button {{on "click" (fn this.updateItems 4)}}>Four Items</button>
</p>
<p>
Test case:
<ol>
<li>Press down arrow twice to get to "three".</li>
<li>Press "Three Items".</li>
<li>Selection should remain at "Three Items".</li>
<li>Press "Two Items".</li>
<li>Selection should move to "Two Items".</li>
<li>Press "Three Items".</li>
<li>Selection should remain at "Two Items".</li>
</ol>
</p>
<ul
{{did-insert this._didInsertElement}}
{{will-destroy this._willDestroyElement}}
>
{{#each @items as |item index|}}
<li class={{if (eq index this.selectedIndex) "selected"}}>
{{item}}
</li>
{{/each}}
</ul>
<p>selectedIndex: {{this.selectedIndex}}</p>
<p>Use up and down arrow keys to move selection</p>
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"@ember/render-modifiers": "1.0.2",
"ember-truth-helpers": "2.1.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.