blob: 66831f6231c60c33779577c509207276f6fff100 [file] [log] [blame]
<!-- The <detail-list-sk> custom element declaration.
Manages a list of child elements like digest-detail-sk
that produce zoom-clicked, triage and commit-info events.
Handles the events and also focus highlighting.
It also responds to keyboard shortcuts. Since keyboard events
are registered against the global 'document' object, it provides
the 'startUse' and 'endUse' functions to indicate when this element
is active. This is particularly important if it's part of dynamic
behavior like pop-up dialogs.
Attributes:
None
Events:
None
Methods:
startUse - to be called before the element is actively being used.
It registers the necessary keyboard shortcuts.
endUse - to be called once the element is not used any more.
openHelpDialog - opens the help dialog for key bindings.
-->
<link rel="import" href="help-dialog-sk.html">
<dom-module id="detail-list-sk">
<template>
<content></content>
<!-- help dialog -->
<help-dialog-sk id="helpDialog">
<table>
<tr><th colspan=2>Keyboard Shortcuts</th></tr>
<tr><th>J</th><td>Next</td></tr>
<tr><th>K</th><td>Prev</td></tr>
<tr><th>W</th><td>Zoom</td></tr>
<tr><th>A</th><td>Postive</td></tr>
<tr><th>S</th><td>Negative</td></tr>
<tr><th>D</th><td>Untriaged</td></tr>
<tr><th>?</th><td>Help</td></tr>
</table>
</help-dialog-sk>
</template>
<script>
Polymer({
is: 'detail-list-sk',
ready: function () {
this.listen(this, 'zoom-dialog-opened', '_handleZoomOpened');
this.listen(this, 'zoom-dialog-closed', '_handleZoomClosed');
},
startUse: function() {
this.listen(document, 'keypress', '_handleKeyDown');
},
endUse: function() {
this.unlisten(document, 'keypress', '_handleKeyDown');
},
openHelpDialog: function() {
this.$.helpDialog.open();
},
_handleKeyDown: function(e) {
if (this._zooming) {
return;
}
var c = String.fromCharCode(e.keyCode).toUpperCase();
switch (c) {
case 'J':
this._focusNext();
break;
case 'K':
this._focusPrev();
break;
case 'A':
this._markFocus('positive');
break;
case 'S':
this._markFocus('negative');
break;
case 'D':
this._markFocus('untriaged');
break;
case 'W':
this._zoomIn();
break;
case '?':
this.openHelpDialog();
break;
}
},
_handleZoomClosed: function () {
this._zooming = false;
},
_handleZoomOpened: function () {
this._zooming = true;
},
// _findFocus returns the current details element with the keyboard focus.
_findFocus: function () {
return $$$('[data-focus]', this);
},
// _moveFocus does the actual work of changing the focus from lastEle
// to nextEle.
_moveFocus: function (lastEle, nextEle) {
// Don't wrap around past the bottom of the list.
if (lastEle != null && nextEle == null) {
return;
}
if (lastEle != null) {
Polymer.dom(lastEle).removeAttribute('data-focus');
}
// If nothing is selected, then focus on the first details element.
if (nextEle == null) {
nextEle = Polymer.dom(this).firstElementChild;
}
Polymer.dom(nextEle).setAttribute('data-focus', 'true');
nextEle.scrollIntoView(true);
},
_focusSet: function (ele) {
var lastEle = this._findFocus();
this._moveFocus(lastEle, ele);
},
// Move the focus to the next digest.
_focusNext: function () {
var nextEle = null;
var lastEle = this._findFocus();
if (lastEle != null) {
nextEle = lastEle.nextElementSibling;
if (nextEle.nodeName == 'TEMPLATE') {
nextEle = null;
}
}
this._moveFocus(lastEle, nextEle);
},
// Move the focus to the previous digest.
_focusPrev: function () {
var nextEle = null;
var lastEle = this._findFocus();
if (lastEle != null) {
nextEle = lastEle.previousElementSibling;
}
this._moveFocus(lastEle, nextEle);
},
_markFocus: function (status) {
var ele = this._findFocus();
if (ele && ele.triggerTriage) {
ele.triggerTriage(status);
}
},
_zoomIn: function () {
const ele = this._findFocus();
if (ele) {
const zoom = $$$('button.zoom_btn', ele);
zoom && zoom.click();
}
}
});
</script>
</dom-module>