lists: implement select-as-you-type
This commit is contained in:
parent
c211b55d3b
commit
64a182ae1d
4 changed files with 85 additions and 61 deletions
|
@ -19,6 +19,7 @@ Ox.IconList <f> IconList Object
|
|||
orientation <s|both> orientation ("horizontal", "vertical" or "both")
|
||||
pageLength <n|100> Number of items per page (if orientation != "both")
|
||||
query <o> Query
|
||||
selectAsYouType <s|''> If set to a key, enables select-as-you-type
|
||||
selected <a|[]> array of selected items
|
||||
size <n|128> list size
|
||||
sort <a|[]> sort keys
|
||||
|
@ -46,6 +47,7 @@ Ox.IconList = function(options, self) {
|
|||
orientation: 'both',
|
||||
pageLength: 100,
|
||||
query: {conditions: [], operator: '&'},
|
||||
selectAsYouType: '',
|
||||
selected: [],
|
||||
size: 128,
|
||||
sort: [],
|
||||
|
@ -95,6 +97,7 @@ Ox.IconList = function(options, self) {
|
|||
orientation: self.options.orientation,
|
||||
pageLength: self.options.pageLength,
|
||||
query: self.options.query,
|
||||
selectAsYouType: self.options.selectAsYouType,
|
||||
selected: self.options.selected,
|
||||
sort: self.options.sort,
|
||||
type: 'icon',
|
||||
|
|
|
@ -21,6 +21,7 @@ Ox.InfoList = function(options, self) {
|
|||
max: -1,
|
||||
min: 0,
|
||||
query: {conditions: [], operator: '&'},
|
||||
selectAsYouType: '',
|
||||
selected: [],
|
||||
size: 192,
|
||||
sort: [],
|
||||
|
@ -71,6 +72,7 @@ Ox.InfoList = function(options, self) {
|
|||
orientation: 'vertical',
|
||||
pageLength: 10,
|
||||
query: self.options.query,
|
||||
selectAsYouType: self.options.selectAsYouType,
|
||||
selected: self.options.selected,
|
||||
sort: self.options.sort,
|
||||
type: 'info',
|
||||
|
|
|
@ -24,6 +24,7 @@ Ox.List <f> List constructor
|
|||
prefixed with `'!'` (not)
|
||||
value <*> Value
|
||||
operator <s> Operator (`'&'` or `'|'`)
|
||||
selectAsYouType <s|''> If set to a key, enables select-as-you-type
|
||||
selected <a|[]> ids of the selected elements
|
||||
sort <a|[]> sort order
|
||||
sortable <b|false> If true, items can be re-ordered
|
||||
|
@ -107,12 +108,12 @@ Ox.List = function(options, self) {
|
|||
that.reloadList();
|
||||
},
|
||||
selected: function() {
|
||||
var previousSelected = self.selected;
|
||||
var previousSelected = Ox.clone(self.selected);
|
||||
setSelected(self.options.selected);
|
||||
// fixme: the following was added in order
|
||||
// to make table list find-as-you-type work,
|
||||
// this may break other things
|
||||
if (!self.isAsync && !Ox.isEqual(self.selected, previousSelected)) {
|
||||
if (/*!self.isAsync && */!Ox.isEqual(self.selected, previousSelected)) {
|
||||
triggerSelectEvent(self.options.selected);
|
||||
}
|
||||
},
|
||||
|
@ -227,10 +228,16 @@ Ox.List = function(options, self) {
|
|||
] = selectNext;
|
||||
if (self.options.max == -1) {
|
||||
self.keyboardEvents[
|
||||
'key_' + (self.options.orientation == 'vertical' ? 'shift_up' : 'shift_left')
|
||||
'key_' + (
|
||||
self.options.orientation == 'vertical'
|
||||
? 'shift_up' : 'shift_left'
|
||||
)
|
||||
] = addPreviousToSelection;
|
||||
self.keyboardEvents[
|
||||
'key_' + (self.options.orientation == 'vertical' ? 'shift_down' : 'shift_right')
|
||||
'key_' + (
|
||||
self.options.orientation == 'vertical'
|
||||
? 'shift_down' : 'shift_right'
|
||||
)
|
||||
] = addNextToSelection;
|
||||
}
|
||||
if (self.options.orientation == 'vertical') {
|
||||
|
@ -258,10 +265,14 @@ Ox.List = function(options, self) {
|
|||
66, 60, 65, 70, 60, 64, 68, 72, 76, 60
|
||||
];
|
||||
}
|
||||
if (self.options.selectAsYouType) {
|
||||
Ox.extend(self.keyboardEvents, {keys: selectAsYouType});
|
||||
}
|
||||
|
||||
that.bindEvent(self.keyboardEvents);
|
||||
|
||||
!self.isAsync ? updateItems() : updateQuery();
|
||||
|
||||
that.bindEvent(self.keyboardEvents);
|
||||
//Ox.UI.$window.resize(that.size); // fixme: this is not the widget's job
|
||||
|
||||
function addAboveToSelection() {
|
||||
|
@ -309,9 +320,7 @@ Ox.List = function(options, self) {
|
|||
}
|
||||
|
||||
function addItem(keys) {
|
||||
that.triggerEvent('add', {
|
||||
keys: keys
|
||||
});
|
||||
that.triggerEvent('add', {keys: keys});
|
||||
}
|
||||
|
||||
function addNextToSelection() {
|
||||
|
@ -335,8 +344,9 @@ Ox.List = function(options, self) {
|
|||
Ox.makeArray(pos).forEach(function(pos) {
|
||||
if (!isSelected(pos)) {
|
||||
self.selected.push(pos);
|
||||
!Ox.isUndefined(self.$items[pos])
|
||||
&& self.$items[pos].addClass('OxSelected');
|
||||
if (!Ox.isUndefined(self.$items[pos])) {
|
||||
self.$items[pos].addClass('OxSelected');
|
||||
}
|
||||
triggerEvent = true;
|
||||
} else {
|
||||
// allow for 'cursor navigation' if orientation == 'both'
|
||||
|
@ -410,6 +420,10 @@ Ox.List = function(options, self) {
|
|||
triggerEvent && triggerSelectEvent();
|
||||
}
|
||||
|
||||
function doubleclick(data) {
|
||||
open(isSpecialTarget(data));
|
||||
}
|
||||
|
||||
function dragstart(data) {
|
||||
var $target = $(data.target),
|
||||
$parent = $target.parent();
|
||||
|
@ -971,36 +985,6 @@ Ox.List = function(options, self) {
|
|||
delete self.drag;
|
||||
}
|
||||
|
||||
function singleclick(data) {
|
||||
// these can't trigger on mousedown, since the mousedown
|
||||
// could still be the start of a doubleclick or drag
|
||||
var pos = findItemPosition(data),
|
||||
$cell, clickable, editable;
|
||||
if (pos > -1) {
|
||||
if (
|
||||
!data.metaKey && !data.shiftKey
|
||||
&& isSelected(pos) && self.selected.length > 1
|
||||
) {
|
||||
// click on one of multiple selected items
|
||||
select(pos);
|
||||
} else if (self.mousedownOnSelectedCell) {
|
||||
$cell = findCell(data);
|
||||
if ($cell) {
|
||||
clickable = $cell.is('.OxClickable');
|
||||
editable = $cell.is('.OxEditable') && !$cell.is('.OxEdit');
|
||||
if (clickable || editable) {
|
||||
// click on a clickable or editable cell
|
||||
triggerClickEvent(clickable ? 'click' : 'edit', self.$items[pos], $cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doubleclick(data) {
|
||||
open(isSpecialTarget(data));
|
||||
}
|
||||
|
||||
function moveItem(startPos, stopPos) {
|
||||
var $item = self.$items[startPos],
|
||||
insert = startPos < stopPos ? 'insertAfter' : 'insertBefore';
|
||||
|
@ -1158,6 +1142,29 @@ Ox.List = function(options, self) {
|
|||
addToSelection(Ox.range(self.listLength));
|
||||
}
|
||||
|
||||
function selectAsYouType(data) {
|
||||
self.options.items({
|
||||
keys: [self.options.unique],
|
||||
query: {
|
||||
conditions: [
|
||||
self.options.query,
|
||||
{
|
||||
key: self.options.selectAsYouType,
|
||||
operator: '^',
|
||||
value: data.keys
|
||||
},
|
||||
],
|
||||
operator: '&'
|
||||
},
|
||||
range: [0, 1],
|
||||
sort: [{key: self.options.selectAsYouType, operator: '+'}]
|
||||
}, function(result) {
|
||||
result.data.items.length && that.options({
|
||||
selected: [result.data.items[0][self.options.unique]]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function selectBelow() {
|
||||
var pos = getBelow();
|
||||
if (pos > -1) {
|
||||
|
@ -1209,9 +1216,10 @@ Ox.List = function(options, self) {
|
|||
self.$items.forEach(function($item, pos) {
|
||||
if (isSelected(pos)) {
|
||||
self.selected.splice(self.selected.indexOf(pos), 1);
|
||||
!Ox.isUndefined(self.$items[pos]) &&
|
||||
if (!Ox.isUndefined(self.$items[pos])) {
|
||||
self.$items[pos].removeClass('OxSelected');
|
||||
}
|
||||
}
|
||||
});
|
||||
ids.forEach(function(id, i) {
|
||||
var pos = getPositionById(id);
|
||||
|
@ -1231,13 +1239,40 @@ Ox.List = function(options, self) {
|
|||
});
|
||||
function select(pos, i) {
|
||||
self.selected.push(pos);
|
||||
!Ox.isUndefined(self.$items[pos]) &&
|
||||
if (!Ox.isUndefined(self.$items[pos])) {
|
||||
self.$items[pos].addClass('OxSelected');
|
||||
}
|
||||
i == 0 && scrollToPosition(pos);
|
||||
++counter == ids.length && callback && callback();
|
||||
}
|
||||
}
|
||||
|
||||
function singleclick(data) {
|
||||
// these can't trigger on mousedown, since the mousedown
|
||||
// could still be the start of a doubleclick or drag
|
||||
var pos = findItemPosition(data),
|
||||
$cell, clickable, editable;
|
||||
if (pos > -1) {
|
||||
if (
|
||||
!data.metaKey && !data.shiftKey
|
||||
&& isSelected(pos) && self.selected.length > 1
|
||||
) {
|
||||
// click on one of multiple selected items
|
||||
select(pos);
|
||||
} else if (self.mousedownOnSelectedCell) {
|
||||
$cell = findCell(data);
|
||||
if ($cell) {
|
||||
clickable = $cell.is('.OxClickable');
|
||||
editable = $cell.is('.OxEditable') && !$cell.is('.OxEdit');
|
||||
if (clickable || editable) {
|
||||
// click on a clickable or editable cell
|
||||
triggerClickEvent(clickable ? 'click' : 'edit', self.$items[pos], $cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSelection(pos) {
|
||||
// FIXME: unused
|
||||
if (!isSelected(pos)) {
|
||||
|
|
|
@ -32,6 +32,7 @@ Ox.TableList <f> TableList Widget
|
|||
pageLength <n|100> Number of items per page
|
||||
query <o> Query
|
||||
scrollbarVisible <b|false> If true, the scrollbar is always visible
|
||||
selectAsYouType <s|''> If set to a key, enables select-as-you-type
|
||||
selected <[s]|[]> Array of selected ids
|
||||
sort <[o]|[s]|[]> ['+foo', ...] or [{key: 'foo', operator: '+'}, ...]
|
||||
sortable <b|false> If true, elements can be re-ordered
|
||||
|
@ -104,8 +105,7 @@ Ox.TableList = function(options, self) {
|
|||
var $element = that.$body.$element,
|
||||
scrollLeft = $element[0].scrollLeft + $element.width();
|
||||
$element.animate({scrollLeft: scrollLeft}, 250);
|
||||
},
|
||||
keys: find
|
||||
}
|
||||
});
|
||||
|
||||
self.options.columns.forEach(function(column) { // fixme: can this go into a generic ox.js function?
|
||||
|
@ -246,6 +246,7 @@ Ox.TableList = function(options, self) {
|
|||
pageLength: self.options.pageLength,
|
||||
paste: self.options.paste,
|
||||
query: self.options.query,
|
||||
selectAsYouType: self.options.selectAsYouType,
|
||||
selected: self.options.selected,
|
||||
sort: self.options.sort,
|
||||
sortable: self.options.sortable,
|
||||
|
@ -596,23 +597,6 @@ Ox.TableList = function(options, self) {
|
|||
});
|
||||
}
|
||||
|
||||
function find(data) {
|
||||
// fixme: works only if items are an array
|
||||
var query = data.keys,
|
||||
sort = self.options.sort[0];
|
||||
Ox.Log('List', 'QUERY', query)
|
||||
Ox.forEach(self.options.items, function(item, i) {
|
||||
var value = (
|
||||
sort.map ? sort.map(item[sort.key]) : item[sort.key]
|
||||
).toString().toLowerCase();
|
||||
if (Ox.startsWith(value, query)) {
|
||||
that.$body.options({selected: [item[self.options.unique]]});
|
||||
Ox.Log('List', 'QUERY', query, 'VALUE', value)
|
||||
Ox.Break();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function formatValue(key, value, data) {
|
||||
// fixme: this may be obscure...
|
||||
// since the format of a value may depend on another value,
|
||||
|
|
Loading…
Reference in a new issue