lists: implement select-as-you-type

This commit is contained in:
rolux 2012-06-29 14:19:34 +02:00
parent c211b55d3b
commit 64a182ae1d
4 changed files with 85 additions and 61 deletions

View file

@ -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',

View file

@ -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',

View file

@ -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,8 +1216,9 @@ 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) {
@ -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)) {

View file

@ -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,