2011-04-23 16:45:50 +00:00
|
|
|
// vim: et:ts=4:sw=4:sts=4:ft=js
|
2011-05-16 10:49:48 +00:00
|
|
|
|
2011-05-16 08:24:46 +00:00
|
|
|
/*@
|
|
|
|
Ox.TextList <f:Ox.Element> TextList Object
|
|
|
|
() -> <f> TextList Object
|
|
|
|
(options) -> <f> TextList Object
|
|
|
|
(options, self) -> <f> TextList Object
|
|
|
|
options <o> Options object
|
2011-05-22 13:14:42 +00:00
|
|
|
columns <[o]|[]>
|
|
|
|
Fixme: There's probably more...
|
|
|
|
addable <b>
|
|
|
|
editable <b>
|
2011-05-22 17:12:21 +00:00
|
|
|
format <f>
|
2011-05-22 13:14:42 +00:00
|
|
|
id <s>
|
|
|
|
removable <b>
|
2011-05-24 12:50:16 +00:00
|
|
|
map <f> function that maps values to sort values
|
2011-05-22 13:14:42 +00:00
|
|
|
operator <s> default sort operator
|
|
|
|
title <s>
|
2011-05-22 17:12:21 +00:00
|
|
|
unique <b> If true, this column acts as unique id
|
2011-05-22 13:14:42 +00:00
|
|
|
visible <b>
|
|
|
|
width <n>
|
2011-05-16 10:49:48 +00:00
|
|
|
columnsMovable <b|false>
|
|
|
|
columnsRemovable <b|false>
|
|
|
|
columnsResizable <b|false>
|
|
|
|
columnsVisible <b|false>
|
|
|
|
columnWidth <a|[40, 800]>
|
|
|
|
id <s|''>
|
|
|
|
items <f|null> function() {} {sort, range, keys, callback} or array
|
|
|
|
max <n|-1>
|
|
|
|
min <n|0>
|
|
|
|
pageLength <n|100>
|
|
|
|
scrollbarVisible <b|false>
|
|
|
|
selected <a|[]>
|
|
|
|
sort <a|[]>
|
2011-05-16 08:24:46 +00:00
|
|
|
self <o> shared private variable
|
|
|
|
@*/
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
Ox.TextList = function(options, self) {
|
|
|
|
|
|
|
|
// fixme: rename to TableList
|
|
|
|
|
|
|
|
var self = self || {},
|
|
|
|
that = new Ox.Element({}, self)
|
|
|
|
.defaults({
|
|
|
|
columns: [],
|
|
|
|
columnsMovable: false,
|
|
|
|
columnsRemovable: false,
|
|
|
|
columnsResizable: false,
|
|
|
|
columnsVisible: false,
|
|
|
|
columnWidth: [40, 800],
|
|
|
|
id: '',
|
|
|
|
items: null, // function() {} {sort, range, keys, callback} or array
|
|
|
|
max: -1,
|
|
|
|
min: 0,
|
|
|
|
pageLength: 100,
|
|
|
|
scrollbarVisible: false,
|
|
|
|
selected: [],
|
|
|
|
sort: []
|
|
|
|
})
|
|
|
|
.options(options || {})
|
2011-05-24 13:44:02 +00:00
|
|
|
.addClass('OxTextList')
|
|
|
|
.bindEvent({
|
|
|
|
key_left: function() {
|
|
|
|
var $element = that.$body.$element;
|
|
|
|
$element[0].scrollLeft = $element[0].scrollLeft - $element.width();
|
|
|
|
},
|
|
|
|
key_right: function() {
|
|
|
|
var $element = that.$body.$element;
|
|
|
|
$element[0].scrollLeft = $element[0].scrollLeft + $element.width();
|
2011-05-24 14:10:08 +00:00
|
|
|
},
|
|
|
|
keys: find
|
2011-05-24 13:44:02 +00:00
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
|
|
|
|
self.options.columns.forEach(function(v) { // fixme: can this go into a generic ox.js function?
|
|
|
|
// fixme: and can't these just remain undefined?
|
|
|
|
if (Ox.isUndefined(v.align)) {
|
|
|
|
v.align = 'left';
|
|
|
|
}
|
|
|
|
if (Ox.isUndefined(v.clickable)) {
|
|
|
|
v.clickable = false;
|
|
|
|
}
|
|
|
|
if (Ox.isUndefined(v.editable)) {
|
|
|
|
v.editable = false;
|
|
|
|
}
|
|
|
|
if (Ox.isUndefined(v.unique)) {
|
|
|
|
v.unique = false;
|
|
|
|
}
|
|
|
|
if (Ox.isUndefined(v.visible)) {
|
|
|
|
v.visible = false;
|
|
|
|
}
|
|
|
|
if (v.unique) {
|
|
|
|
self.unique = v.id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$.extend(self, {
|
|
|
|
columnPositions: [],
|
|
|
|
defaultColumnWidths: $.map(self.options.columns, function(v) {
|
|
|
|
return v.defaultWidth || v.width;
|
|
|
|
}),
|
|
|
|
itemHeight: 16,
|
|
|
|
page: 0,
|
|
|
|
pageLength: 100,
|
|
|
|
scrollLeft: 0,
|
|
|
|
selectedColumn: getColumnIndexById(self.options.sort[0].key),
|
|
|
|
visibleColumns: $.map(self.options.columns, function(v) {
|
|
|
|
return v.visible ? v : null;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
// fixme: there might be a better way than passing both visible and position
|
|
|
|
self.options.columns.forEach(function(v) {
|
|
|
|
if (!Ox.isUndefined(v.position)) {
|
|
|
|
self.visibleColumns[v.position] = v;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
$.extend(self, {
|
|
|
|
columnWidths: $.map(self.visibleColumns, function(v, i) {
|
|
|
|
return v.width;
|
|
|
|
}),
|
|
|
|
pageHeight: self.options.pageLength * self.itemHeight
|
|
|
|
});
|
|
|
|
|
|
|
|
self.format = {};
|
|
|
|
self.options.columns.forEach(function(v, i) {
|
|
|
|
if (v.format) {
|
|
|
|
self.format[v.id] = v.format;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Head
|
|
|
|
|
|
|
|
if (self.options.columnsVisible) {
|
|
|
|
that.$bar = new Ox.Bar({
|
|
|
|
orientation: 'horizontal',
|
|
|
|
size: 16
|
|
|
|
}).appendTo(that);
|
|
|
|
that.$head = new Ox.Container()
|
|
|
|
.addClass('OxHead')
|
|
|
|
.css({
|
|
|
|
right: self.options.scrollbarVisible ? Ox.UI.SCROLLBAR_SIZE + 'px' : 0
|
|
|
|
})
|
|
|
|
.appendTo(that.$bar);
|
|
|
|
that.$head.$content.addClass('OxTitles');
|
|
|
|
constructHead();
|
|
|
|
if (self.options.columnsRemovable) {
|
|
|
|
that.$select = new Ox.Select({
|
|
|
|
id: self.options.id + 'SelectColumns',
|
|
|
|
items: $.map(self.options.columns, function(v, i) {
|
|
|
|
return {
|
|
|
|
checked: v.visible,
|
|
|
|
disabled: v.removable === false,
|
|
|
|
id: v.id,
|
|
|
|
title: v.title
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
max: -1,
|
|
|
|
min: 1,
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.bindEvent('change', changeColumns)
|
|
|
|
.appendTo(that.$bar.$element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Body
|
|
|
|
|
|
|
|
that.$body = new Ox.List({
|
|
|
|
construct: constructItem,
|
|
|
|
id: self.options.id,
|
|
|
|
items: self.options.items,
|
|
|
|
itemHeight: 16,
|
|
|
|
items: self.options.items,
|
|
|
|
itemWidth: getItemWidth(),
|
|
|
|
format: self.format, // fixme: not needed, happens in TextList
|
|
|
|
keys: $.map(self.visibleColumns, function(v) {
|
|
|
|
return v.id;
|
|
|
|
}),
|
|
|
|
max: self.options.max,
|
|
|
|
min: self.options.min,
|
|
|
|
pageLength: self.options.pageLength,
|
|
|
|
paste: self.options.paste,
|
|
|
|
orientation: 'vertical',
|
|
|
|
selected: self.options.selected,
|
|
|
|
sort: self.options.sort,
|
|
|
|
sortable: self.options.sortable,
|
|
|
|
type: 'text',
|
|
|
|
unique: self.unique
|
|
|
|
}, $.extend({}, self)) // pass event handler
|
|
|
|
.addClass('OxBody')
|
|
|
|
.css({
|
|
|
|
top: (self.options.columnsVisible ? 16 : 0) + 'px',
|
|
|
|
overflowY: (self.options.scrollbarVisible ? 'scroll' : 'hidden')
|
|
|
|
})
|
|
|
|
.scroll(function() {
|
|
|
|
var scrollLeft = $(this).scrollLeft();
|
|
|
|
if (scrollLeft != self.scrollLeft) {
|
|
|
|
self.scrollLeft = scrollLeft;
|
|
|
|
that.$head && that.$head.scrollLeft(scrollLeft);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
edit: function(event, data) {
|
|
|
|
that.editCell(data.id, data.key);
|
|
|
|
},
|
|
|
|
select: function(event, data) {
|
|
|
|
self.options.selected = data.ids;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.appendTo(that);
|
|
|
|
that.$body.$content.css({
|
|
|
|
width: getItemWidth() + 'px'
|
|
|
|
});
|
|
|
|
|
|
|
|
//Ox.print('s.vC', self.visibleColumns)
|
|
|
|
|
|
|
|
function addColumn(id) {
|
|
|
|
//Ox.print('addColumn', id);
|
|
|
|
var column, ids,
|
|
|
|
index = 0;
|
|
|
|
Ox.forEach(self.options.columns, function(v) {
|
|
|
|
if (v.visible) {
|
|
|
|
index++;
|
|
|
|
} else if (v.id == id) {
|
|
|
|
column = v;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
column.visible = true;
|
|
|
|
self.visibleColumns.splice(index, 0, column);
|
|
|
|
self.columnWidths.splice(index, 0, column.width);
|
|
|
|
that.$head.$content.empty();
|
|
|
|
constructHead();
|
|
|
|
that.$body.options({
|
|
|
|
keys: $.map(self.visibleColumns, function(v, i) {
|
|
|
|
return v.id;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
that.$body.reloadPages();
|
|
|
|
}
|
|
|
|
|
|
|
|
function changeColumns(event, data) {
|
|
|
|
var add,
|
|
|
|
ids = [];
|
|
|
|
Ox.forEach(data.selected, function(column) {
|
|
|
|
var index = getColumnIndexById(column.id);
|
|
|
|
if (!self.options.columns[index].visible) {
|
|
|
|
addColumn(column.id);
|
|
|
|
add = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ids.push(column.id);
|
|
|
|
});
|
|
|
|
if (!add) {
|
|
|
|
Ox.forEach(self.visibleColumns, function(column) {
|
|
|
|
if (ids.indexOf(column.id) == -1) {
|
|
|
|
removeColumn(column.id);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
triggerColumnChangeEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickColumn(id) {
|
|
|
|
Ox.print('clickColumn', id);
|
|
|
|
var i = getColumnIndexById(id),
|
|
|
|
isSelected = self.options.sort[0].key == self.options.columns[i].id;
|
2011-05-24 13:44:02 +00:00
|
|
|
self.options.sort = [{
|
|
|
|
key: self.options.columns[i].id,
|
|
|
|
operator: isSelected ?
|
|
|
|
(self.options.sort[0].operator == '+' ? '-' : '+') :
|
|
|
|
self.options.columns[i].operator,
|
|
|
|
map: self.options.columns[i].map
|
|
|
|
}]
|
|
|
|
updateColumn();
|
|
|
|
// fixme: strangely, sorting the list blocks updating the column,
|
|
|
|
// so we use a timeout for now
|
|
|
|
setTimeout(function() {
|
|
|
|
that.$body.options({sort: self.options.sort});
|
|
|
|
}, 10)
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function constructHead() {
|
|
|
|
var offset = 0;
|
|
|
|
that.$titles = [];
|
|
|
|
self.columnOffsets = [];
|
|
|
|
self.visibleColumns.forEach(function(v, i) {
|
|
|
|
var $order, $resize, $left, $center, $right;
|
|
|
|
offset += self.columnWidths[i];
|
|
|
|
self.columnOffsets[i] = offset - self.columnWidths[i] / 2;
|
|
|
|
that.$titles[i] = new Ox.Element()
|
|
|
|
.addClass('OxTitle OxColumn' + Ox.toTitleCase(v.id))
|
|
|
|
.css({
|
|
|
|
width: (self.columnWidths[i] - 9) + 'px',
|
|
|
|
textAlign: v.align
|
|
|
|
})
|
|
|
|
.html(v.title)
|
2011-05-22 17:12:21 +00:00
|
|
|
.appendTo(that.$head.$content.$element);
|
|
|
|
// if sort operator is set, bind click event
|
|
|
|
if (v.operator) {
|
|
|
|
that.$titles[i].bindEvent({
|
2011-04-22 22:03:10 +00:00
|
|
|
anyclick: function(event, e) {
|
|
|
|
clickColumn(v.id);
|
2011-05-22 17:12:21 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
// if columns are movable, bind drag events
|
|
|
|
if (self.options.columnsMovable) {
|
|
|
|
that.$titles[i].bindEvent({
|
2011-04-22 22:03:10 +00:00
|
|
|
dragstart: function(event, e) {
|
|
|
|
dragstartColumn(v.id, e);
|
|
|
|
},
|
|
|
|
drag: function(event, e) {
|
|
|
|
dragColumn(v.id, e);
|
|
|
|
},
|
|
|
|
dragend: function(event, e) {
|
|
|
|
dragendColumn(v.id, e);
|
|
|
|
}
|
|
|
|
})
|
2011-05-22 17:12:21 +00:00
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
$order = $('<div>')
|
|
|
|
.addClass('OxOrder')
|
|
|
|
.html(Ox.UI.symbols['triangle_' + (
|
|
|
|
v.operator == '+' ? 'up' : 'down'
|
|
|
|
)])
|
|
|
|
.click(function() {
|
|
|
|
$(this).prev().trigger('click')
|
|
|
|
})
|
|
|
|
.appendTo(that.$head.$content.$element);
|
|
|
|
$resize = new Ox.Element()
|
|
|
|
.addClass('OxResize')
|
|
|
|
.appendTo(that.$head.$content.$element);
|
2011-05-22 17:12:21 +00:00
|
|
|
// if columns are resizable, bind click and drag events
|
2011-04-22 22:03:10 +00:00
|
|
|
if (self.options.columnsResizable) {
|
|
|
|
$resize.addClass('OxResizable')
|
|
|
|
.bindEvent({
|
|
|
|
doubleclick: function(event, e) {
|
|
|
|
resetColumn(v.id, e);
|
|
|
|
},
|
|
|
|
dragstart: function(event, e) {
|
|
|
|
dragstartResize(v.id, e);
|
|
|
|
},
|
|
|
|
drag: function(event, e) {
|
|
|
|
dragResize(v.id, e);
|
|
|
|
},
|
|
|
|
dragend: function(event, e) {
|
|
|
|
dragendResize(v.id, e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
$left = $('<div>').addClass('OxLeft').appendTo($resize.$element);
|
|
|
|
$center = $('<div>').addClass('OxCenter').appendTo($resize.$element);
|
|
|
|
$right = $('<div>').addClass('OxRight').appendTo($resize.$element);
|
|
|
|
});
|
|
|
|
that.$head.$content.css({
|
|
|
|
width: (Ox.sum(self.columnWidths) + 2) + 'px'
|
|
|
|
});
|
|
|
|
if (getColumnPositionById(self.options.columns[self.selectedColumn].id) > -1) { // fixme: save in var
|
|
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
|
|
that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({
|
|
|
|
width: (self.options.columns[self.selectedColumn].width - 25) + 'px'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function constructItem(data) {
|
|
|
|
var $item = $('<div>')
|
|
|
|
.addClass('OxTarget')
|
|
|
|
.css({
|
|
|
|
width: getItemWidth() + 'px'
|
|
|
|
});
|
|
|
|
self.visibleColumns.forEach(function(v, i) {
|
2011-05-24 11:43:27 +00:00
|
|
|
//Ox.print(data[v.id], '(--value--)')
|
2011-04-22 22:03:10 +00:00
|
|
|
var clickable = Ox.isBoolean(v.clickable) ? v.clickable : v.clickable(data),
|
|
|
|
editable = Ox.isBoolean(v.editable) ? v.editable : v.editable(data),
|
|
|
|
$cell = $('<div>')
|
|
|
|
.addClass(
|
|
|
|
'OxCell OxColumn' + Ox.toTitleCase(v.id) +
|
|
|
|
(clickable ? ' OxClickable' : '') +
|
|
|
|
(editable ? ' OxEditable' : '')
|
|
|
|
)
|
|
|
|
.css({
|
|
|
|
width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px',
|
|
|
|
borderRightWidth: (self.options.columnsVisible ? 1 : 0) + 'px',
|
|
|
|
textAlign: v.align
|
|
|
|
})
|
|
|
|
.html(v.id in data ? formatValue(data[v.id], v.format) : '')
|
|
|
|
.appendTo($item);
|
|
|
|
});
|
|
|
|
function formatValue(value, format) {
|
|
|
|
if (value === null) {
|
|
|
|
value = '';
|
|
|
|
} else if (format) {
|
|
|
|
value = Ox.isObject(format) ?
|
|
|
|
Ox['format' + Ox.toTitleCase(format.type)]
|
|
|
|
.apply(this, $.merge([value], format.args)) :
|
|
|
|
format(value);
|
|
|
|
} else if (Ox.isArray(value)) {
|
|
|
|
value = value.join(', ');
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
//Math.random() < 0.01 && Ox.print('item', data, $item);
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragstartColumn(id, e) {
|
|
|
|
self.drag = {
|
|
|
|
startX: e.clientX,
|
|
|
|
startPos: getColumnPositionById(id)
|
|
|
|
}
|
|
|
|
$.extend(self.drag, {
|
|
|
|
stopPos: self.drag.startPos,
|
|
|
|
offsets: $.map(self.visibleColumns, function(v, i) {
|
|
|
|
return self.columnOffsets[i] - self.columnOffsets[self.drag.startPos]
|
|
|
|
})
|
|
|
|
});
|
|
|
|
$('.OxColumn' + Ox.toTitleCase(id)).css({
|
|
|
|
opacity: 0.25
|
|
|
|
});
|
|
|
|
that.$titles[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work?
|
|
|
|
cursor: 'move'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragColumn(id, e) {
|
|
|
|
var d = e.clientX - self.drag.startX,
|
|
|
|
pos = self.drag.stopPos;
|
|
|
|
Ox.forEach(self.drag.offsets, function(v, i) {
|
|
|
|
if (d < 0 && d < v) {
|
|
|
|
self.drag.stopPos = i;
|
|
|
|
return false;
|
|
|
|
} else if (d > 0 && d > v) {
|
|
|
|
self.drag.stopPos = i;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (self.drag.stopPos != pos) {
|
|
|
|
moveColumn(id, self.drag.stopPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragendColumn(id, e) {
|
|
|
|
var column = self.visibleColumns.splice(self.drag.stopPos, 1)[0],
|
|
|
|
width = self.columnWidths.splice(self.drag.stopPos, 1)[0];
|
|
|
|
self.visibleColumns.splice(self.drag.stopPos, 0, column);
|
|
|
|
self.columnWidths.splice(self.drag.stopPos, 0, width);
|
|
|
|
that.$head.$content.empty();
|
|
|
|
constructHead();
|
|
|
|
$('.OxColumn' + Ox.toTitleCase(id)).css({
|
|
|
|
opacity: 1
|
|
|
|
});
|
|
|
|
that.$titles[self.drag.stopPos].removeClass('OxDrag').css({
|
|
|
|
cursor: 'pointer'
|
|
|
|
});
|
|
|
|
that.$body.clearCache();
|
|
|
|
triggerColumnChangeEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragstartResize(id, e) {
|
|
|
|
var pos = getColumnPositionById(id);
|
|
|
|
self.drag = {
|
|
|
|
startX: e.clientX,
|
|
|
|
startWidth: self.columnWidths[pos]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragResize(id, e) {
|
|
|
|
var width = Ox.limit(
|
|
|
|
self.drag.startWidth - self.drag.startX + e.clientX,
|
|
|
|
self.options.columnWidth[0],
|
|
|
|
self.options.columnWidth[1]
|
|
|
|
);
|
|
|
|
resizeColumn(id, width);
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragendResize(id, e) {
|
|
|
|
var pos = getColumnPositionById(id);
|
|
|
|
that.triggerEvent('columnresize', {
|
|
|
|
id: id,
|
|
|
|
width: self.columnWidths[pos]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-05-24 14:10:08 +00:00
|
|
|
function find(data) {
|
|
|
|
// fixme: works only if items are an array
|
|
|
|
var query = data.keys,
|
|
|
|
sort = self.options.sort[0];
|
|
|
|
Ox.forEach(self.options.items, function(item, i) {
|
|
|
|
var value = (
|
|
|
|
sort.map ? sort.map(item[sort.key]) : item[sort.key]
|
|
|
|
).toLowerCase();
|
|
|
|
if (Ox.startsWith(value, query)) {
|
|
|
|
that.$body.options({selected: [item[self.unique]]});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
function getCell(id, key) {
|
|
|
|
Ox.print('getCell', id, key)
|
|
|
|
var $item = getItem(id);
|
|
|
|
return $($item.find('.OxCell.OxColumn' + Ox.toTitleCase(key))[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getColumnIndexById(id) {
|
|
|
|
return Ox.getPositionById(self.options.columns, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getColumnPositionById(id) {
|
|
|
|
return Ox.getPositionById(self.visibleColumns, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getItem(id) {
|
|
|
|
//Ox.print('getItem', id)
|
|
|
|
var $item = null;
|
|
|
|
$.each(that.find('.OxItem'), function(i, v) {
|
|
|
|
$v = $(v);
|
|
|
|
if ($v.data('id') == id) {
|
|
|
|
$item = $v;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getItemWidth() {
|
|
|
|
return Math.max(
|
|
|
|
Ox.sum(self.columnWidths),
|
|
|
|
that.$element.width() -
|
|
|
|
(self.options.scrollbarVisible ? Ox.UI.SCROLLBAR_SIZE : 0)
|
|
|
|
);
|
|
|
|
//return Ox.sum(self.columnWidths)
|
|
|
|
}
|
|
|
|
|
|
|
|
function moveColumn(id, pos) {
|
|
|
|
// fixme: column head should be one element, not three
|
|
|
|
//Ox.print('moveColumn', id, pos)
|
|
|
|
var startPos = getColumnPositionById(id),
|
|
|
|
stopPos = pos,
|
|
|
|
startClassName = '.OxColumn' + Ox.toTitleCase(id),
|
|
|
|
stopClassName = '.OxColumn' + Ox.toTitleCase(self.visibleColumns[stopPos].id),
|
|
|
|
insert = startPos < stopPos ? 'insertAfter' : 'insertBefore'
|
|
|
|
$column = $('.OxTitle' + startClassName),
|
|
|
|
$order = $column.next(),
|
|
|
|
$resize = $order.next();
|
|
|
|
//Ox.print(startClassName, insert, stopClassName)
|
|
|
|
$column.detach()[insert](insert == 'insertAfter' ? $('.OxTitle' + stopClassName).next().next() : $('.OxTitle' + stopClassName));
|
|
|
|
$order.detach().insertAfter($column);
|
|
|
|
$resize.detach().insertAfter($order);
|
|
|
|
$.each(that.$body.find('.OxItem'), function(i, v) {
|
|
|
|
var $v = $(v);
|
|
|
|
$v.children(startClassName).detach()[insert]($v.children(stopClassName));
|
|
|
|
});
|
|
|
|
var column = self.visibleColumns.splice(startPos, 1)[0],
|
|
|
|
width = self.columnWidths.splice(startPos, 1)[0];
|
|
|
|
self.visibleColumns.splice(stopPos, 0, column);
|
|
|
|
self.columnWidths.splice(stopPos, 0, width);
|
|
|
|
}
|
|
|
|
|
|
|
|
function removeColumn(id) {
|
|
|
|
//Ox.print('removeColumn', id);
|
|
|
|
var className = '.OxColumn' + Ox.toTitleCase(id),
|
|
|
|
index = getColumnIndexById(id),
|
|
|
|
itemWidth,
|
|
|
|
position = getColumnPositionById(id),
|
|
|
|
$column = $('.OxTitle' + className),
|
|
|
|
$order = $column.next(),
|
|
|
|
$resize = $order.next();
|
|
|
|
self.options.columns[index].visible = false;
|
|
|
|
self.visibleColumns.splice(position, 1);
|
|
|
|
self.columnWidths.splice(position, 1);
|
|
|
|
that.$head.$content.empty();
|
|
|
|
constructHead();
|
|
|
|
itemWidth = getItemWidth();
|
|
|
|
$.each(that.$body.find('.OxItem'), function(i, v) {
|
|
|
|
var $v = $(v);
|
|
|
|
$v.children(className).remove();
|
|
|
|
$v.css({
|
|
|
|
width: itemWidth + 'px'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
that.$body.$content.css({
|
|
|
|
width: itemWidth + 'px'
|
|
|
|
});
|
|
|
|
that.$body.options({
|
|
|
|
keys: $.map(self.visibleColumns, function(v, i) {
|
|
|
|
return v.id;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
//that.$body.clearCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetColumn(id) {
|
|
|
|
var width = self.defaultColumnWidths[getColumnIndexById(id)];
|
|
|
|
resizeColumn(id, width);
|
|
|
|
that.triggerEvent('columnresize', {
|
|
|
|
id: id,
|
|
|
|
width: width
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeColumn(id, width) {
|
|
|
|
var i = getColumnIndexById(id),
|
|
|
|
pos = getColumnPositionById(id);
|
|
|
|
self.options.columns[i].width = width;
|
|
|
|
self.columnWidths[pos] = width;
|
|
|
|
if (self.options.columnsVisible) {
|
|
|
|
that.$head.$content.css({
|
|
|
|
width: (Ox.sum(self.columnWidths) + 2) + 'px'
|
|
|
|
});
|
|
|
|
that.$titles[pos].css({
|
|
|
|
width: (width - 9 - (i == self.selectedColumn ? 16 : 0)) + 'px'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
that.find('.OxCell.OxColumn' + Ox.toTitleCase(self.options.columns[i].id)).css({
|
|
|
|
width: (width - (self.options.columnsVisible ? 9 : 8)) + 'px'
|
|
|
|
});
|
|
|
|
setWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
function setWidth() {
|
|
|
|
var width = getItemWidth();
|
|
|
|
that.$body.$content.find('.OxItem').css({ // fixme: can we avoid this lookup?
|
|
|
|
width: width + 'px'
|
|
|
|
});
|
|
|
|
that.$body.$content.css({
|
|
|
|
width: width + 'px' // fixme: check if scrollbar visible, and listen to resize/toggle event
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function toggleSelected(id) {
|
|
|
|
var pos = getColumnPositionById(id);
|
|
|
|
if (pos > -1) {
|
|
|
|
updateOrder(id);
|
|
|
|
pos > 0 && that.$titles[pos].prev().children().eq(2).toggleClass('OxSelected');
|
|
|
|
that.$titles[pos].toggleClass('OxSelected');
|
|
|
|
that.$titles[pos].next().toggleClass('OxSelected');
|
|
|
|
that.$titles[pos].next().next().children().eq(0).toggleClass('OxSelected');
|
|
|
|
that.$titles[pos].css({
|
|
|
|
width: (
|
|
|
|
that.$titles[pos].width() + (that.$titles[pos].hasClass('OxSelected') ? -16 : 16)
|
|
|
|
) + 'px'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function triggerColumnChangeEvent() {
|
|
|
|
that.triggerEvent('columnchange', {
|
|
|
|
ids: $.map(self.visibleColumns, function(v, i) {
|
|
|
|
return v.id;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-05-24 13:44:02 +00:00
|
|
|
function updateColumn() {
|
|
|
|
var columnId = self.options.columns[self.selectedColumn].id
|
|
|
|
isSelected = columnId == self.options.sort[0].key;
|
|
|
|
if (self.options.columnsVisible) {
|
|
|
|
if (isSelected) {
|
|
|
|
updateOrder(columnId);
|
|
|
|
} else {
|
|
|
|
toggleSelected(columnId);
|
|
|
|
self.selectedColumn = getColumnIndexById(self.options.sort[0].key);
|
|
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
function updateOrder(id) {
|
|
|
|
var pos = getColumnPositionById(id);
|
|
|
|
//Ox.print(id, pos)
|
|
|
|
that.$titles[pos].next().html(Ox.UI.symbols[
|
|
|
|
'triangle_' + (self.options.sort[0].operator == '+' ? 'up' : 'down')
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
self.setOption = function(key, value) {
|
2011-05-24 11:43:27 +00:00
|
|
|
//Ox.print('---------------------------- TextList setOption', key, value)
|
2011-04-22 22:03:10 +00:00
|
|
|
if (key == 'items') {
|
|
|
|
that.$body.options(key, value);
|
|
|
|
} else if (key == 'paste') {
|
|
|
|
that.$body.options(key, value);
|
|
|
|
} else if (key == 'selected') {
|
|
|
|
that.$body.options(key, value);
|
2011-05-24 13:44:02 +00:00
|
|
|
} else if (key == 'sort') {
|
|
|
|
updateColumn();
|
|
|
|
that.$body.options(key, value);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// fixme: doesn't work, doesn't return that
|
|
|
|
that.closePreview = that.$body.closePreview;
|
|
|
|
|
2011-05-24 10:44:34 +00:00
|
|
|
that.addItem = function(item) {
|
|
|
|
/*
|
|
|
|
self.options.items.push(item);
|
|
|
|
that.$body.options({items: self.options.items});
|
|
|
|
//that.$body.options({selected: [item.id]});
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
that.editCell = function(id, key) {
|
|
|
|
Ox.print('editCell', id, key)
|
|
|
|
var $item = getItem(id),
|
|
|
|
$cell = getCell(id, key),
|
|
|
|
$input,
|
|
|
|
html = $cell.html(),
|
|
|
|
index = getColumnIndexById(key),
|
|
|
|
column = self.options.columns[index],
|
|
|
|
width = column.width - self.options.columnsVisible;
|
|
|
|
$cell.empty()
|
|
|
|
.addClass('OxEdit')
|
|
|
|
.css({
|
|
|
|
width: width + 'px'
|
|
|
|
});
|
|
|
|
$input = new Ox.Input({
|
|
|
|
autovalidate: column.input ? column.input.autovalidate : null,
|
|
|
|
style: 'square',
|
|
|
|
value: html,
|
|
|
|
width: width
|
|
|
|
})
|
|
|
|
.bind({
|
|
|
|
mousedown: function(e) {
|
|
|
|
// keep mousedown from reaching list
|
|
|
|
e.stopPropagation();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
blur: submit,
|
|
|
|
})
|
|
|
|
.appendTo($cell);
|
|
|
|
//.focusInput();
|
|
|
|
setTimeout($input.focusInput, 0); // fixme: strange
|
|
|
|
function submit() {
|
|
|
|
var value = $input.value();
|
|
|
|
//$input.loseFocus().remove();
|
|
|
|
// fixme: leaky, inputs remain in focus stack
|
|
|
|
$cell.removeClass('OxEdit')
|
|
|
|
.css({
|
|
|
|
width: (width - 8) + 'px'
|
|
|
|
})
|
|
|
|
.html(value)
|
|
|
|
that.triggerEvent('submit', {
|
|
|
|
id: id,
|
|
|
|
key: key,
|
|
|
|
value: value
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
that.gainFocus = function() {
|
|
|
|
that.$body.gainFocus();
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.loseFocus = function() {
|
|
|
|
that.$body.loseFocus();
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
|
|
|
|
that.paste = function(data) {
|
|
|
|
that.$body.paste();
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.reloadList = function() {
|
|
|
|
that.$body.reloadList();
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.resizeColumn = function(id, width) {
|
|
|
|
resizeColumn(id, width);
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
|
|
|
|
that.size = function() {
|
|
|
|
setWidth();
|
|
|
|
that.$body.size();
|
|
|
|
}
|
|
|
|
|
2011-05-24 13:44:02 +00:00
|
|
|
// fixme: deprecated
|
2011-04-22 22:03:10 +00:00
|
|
|
that.sortList = function(key, operator) {
|
2011-05-24 13:44:02 +00:00
|
|
|
Ox.print('$$$$ DEPRECATED $$$$')
|
2011-04-22 22:03:10 +00:00
|
|
|
var isSelected = key == self.options.sort[0].key;
|
2011-05-24 12:50:16 +00:00
|
|
|
self.options.sort = [{
|
|
|
|
key: key,
|
|
|
|
operator: operator,
|
|
|
|
map: self.options.columns[self.selectedColumn].sort
|
|
|
|
}];
|
2011-04-22 22:03:10 +00:00
|
|
|
if (self.options.columnsVisible) {
|
|
|
|
if (isSelected) {
|
|
|
|
updateOrder(self.options.columns[self.selectedColumn].id);
|
|
|
|
} else {
|
|
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
|
|
self.selectedColumn = getColumnIndexById(key);
|
|
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
|
|
}
|
|
|
|
}
|
2011-05-22 17:12:21 +00:00
|
|
|
// fixme: strangely, sorting the list blocks toggling the selection,
|
|
|
|
// so we use a timeout for now
|
|
|
|
setTimeout(function() {
|
2011-05-24 13:44:02 +00:00
|
|
|
that.$body.options({sort: self.options.sort});
|
|
|
|
/*
|
2011-05-22 17:12:21 +00:00
|
|
|
that.$body.sortList(
|
|
|
|
self.options.sort[0].key,
|
|
|
|
self.options.sort[0].operator,
|
2011-05-24 12:50:16 +00:00
|
|
|
self.options.sort[0].map
|
2011-05-22 17:12:21 +00:00
|
|
|
);
|
2011-05-24 13:44:02 +00:00
|
|
|
*/
|
2011-05-22 17:12:21 +00:00
|
|
|
}, 10);
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.value = function(id, key, value) {
|
|
|
|
// fixme: make this accept id, {k: v, ...}
|
2011-05-24 06:15:44 +00:00
|
|
|
Ox.print('value', id, key, value)
|
2011-04-22 22:03:10 +00:00
|
|
|
var $item = getItem(id),
|
2011-05-24 06:15:44 +00:00
|
|
|
$cell = getCell(id, key),
|
2011-04-22 22:03:10 +00:00
|
|
|
column = self.options.columns[getColumnIndexById(key)];
|
|
|
|
if (arguments.length == 1) {
|
|
|
|
return that.$body.value(id);
|
|
|
|
} else if (arguments.length == 2) {
|
|
|
|
return that.$body.value(id, key);
|
|
|
|
} else {
|
|
|
|
that.$body.value(id, key, value);
|
2011-05-24 06:15:44 +00:00
|
|
|
$cell && $cell.html(column.format ? column.format(value) : value);
|
2011-04-22 22:03:10 +00:00
|
|
|
/*
|
|
|
|
if (column.unique) {
|
|
|
|
that.$body.setId($item.data('id'), value);
|
|
|
|
$item.data({id: value});
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return that;
|
|
|
|
|
|
|
|
};
|