oxjs/source/Ox.UI/js/List/TreeList.js

296 lines
8.9 KiB
JavaScript
Raw Normal View History

2011-11-05 16:46:53 +00:00
'use strict';
2011-05-16 08:24:46 +00:00
/*@
2012-06-13 13:53:20 +00:00
Ox.TreeList <f> Tree List
([options[, self]]) -> <o:Ox.List> Tree List Object
2011-05-16 08:24:46 +00:00
options <o> Options object
2012-06-13 13:53:20 +00:00
data <f|null> Data to be parsed as items (needs documentation)
expanded <b|false> If true, and data is not null, all items are expanded
2012-06-12 11:13:23 +00:00
icon <o|f|null> Image URL, or function that returns an image object
2012-06-13 13:53:20 +00:00
items <a|[]> Array of items
max <n|-1> Maximum number of items that can be selected, -1 unlimited
min <n|0> Minimum number of items that have to be selected
selected <a|[]> Selected ids
width <n|256> List width
self <o> Shared private variable
2011-05-16 08:24:46 +00:00
@*/
2011-04-22 22:03:10 +00:00
Ox.TreeList = function(options, self) {
// fixme: expanding the last item should cause some scroll
self = self || {};
var that = Ox.Element({}, self)
2011-04-22 22:03:10 +00:00
.defaults({
data: null,
2012-06-13 13:53:20 +00:00
expanded: false,
2012-06-12 11:13:23 +00:00
icon: null,
2011-04-22 22:03:10 +00:00
items: [],
max: 1,
2011-04-22 22:03:10 +00:00
min: 0,
selected: [],
width: 'auto'
2011-04-22 22:03:10 +00:00
})
2012-05-28 19:35:41 +00:00
.options(options || {})
.update({
data: function() {
// ...
},
selected: function() {
//self.$list.options({selected: self.options.selected});
selectItem({ids: self.options.selected});
self.$list.scrollToSelection();
},
width: function() {
// ...
}
});
2011-04-22 22:03:10 +00:00
if (self.options.data) {
self.options.items = [];
2012-05-22 07:11:26 +00:00
Ox.sort(Object.keys(self.options.data)).forEach(function(key) {
self.options.items.push(parseData(key, self.options.data[key]));
2011-04-22 22:03:10 +00:00
});
}
2012-04-08 12:38:15 +00:00
that.setElement(
self.$list = Ox.List({
_tree: true,
construct: constructItem,
itemHeight: 16,
items: parseItems(),
itemWidth: self.options.width,
keys: ['expanded', 'id', 'items', 'level', 'title'],
max: self.options.max,
min: self.options.min,
unique: 'id'
}, Ox.clone(self))
2012-04-08 12:38:15 +00:00
.addClass('OxTextList OxTreeList')
.css({
width: self.options.width + 'px',
overflowY: 'scroll'
})
.bindEvent({
anyclick: clickItem,
2012-04-09 08:41:06 +00:00
select: selectItem,
2012-04-08 12:38:15 +00:00
toggle: toggleItems
})
);
2011-04-22 22:03:10 +00:00
2012-04-09 08:41:06 +00:00
self.options.selected.length && selectItem({ids: self.options.selected});
2011-04-22 22:03:10 +00:00
function clickItem(e) {
var $target = $(e.target),
$item, id, item;
if ($target.is('.OxToggle')) {
2011-04-22 22:03:10 +00:00
$item = $target.parent().parent();
id = $item.data('id');
item = getItemById(id);
toggleItem(item, !item.expanded);
2011-04-22 22:03:10 +00:00
}
}
function constructItem(data) {
2012-06-12 11:13:23 +00:00
var $item = $('<div>').css({
width: self.options.width - Ox.UI.SCROLLBAR_SIZE + 'px'
}),
$cell = $('<div>').addClass('OxCell').css({width: '8px'}),
$icon = data.id ? getIcon(data.id, data.expanded || (
data.items ? false : null
)) : null,
padding = data.level * 16 - 8;
if (data.level) {
2011-04-22 22:03:10 +00:00
$('<div>')
.addClass('OxCell OxTarget')
2012-06-12 11:13:23 +00:00
.css({width: padding + 'px'})
2011-04-22 22:03:10 +00:00
.appendTo($item);
}
2012-06-12 11:13:23 +00:00
$cell.appendTo($item);
$icon && $icon.addClass(data.items ? 'OxToggle' : 'OxTarget').appendTo($cell);
2011-04-22 22:03:10 +00:00
$('<div>')
2012-04-09 08:41:06 +00:00
.addClass('OxCell OxTarget' + (!data.items ? ' OxSelectable' : ''))
2011-04-22 22:03:10 +00:00
.css({
width: self.options.width - padding - 32 - Ox.UI.SCROLLBAR_SIZE + 'px'
2011-04-22 22:03:10 +00:00
})
.html(data.title || '')
2011-04-22 22:03:10 +00:00
.appendTo($item);
return $item;
}
2012-06-12 11:13:23 +00:00
function getIcon(id, expanded) {
var isFunction = Ox.isFunction(self.options.icon),
$icon = isFunction ? self.options.icon(id, expanded) : null;
if (!$icon) {
if (expanded === null) {
if (!$icon && self.options.icon && !isFunction) {
$icon = $('<img>').attr({src: self.options.icon});
}
} else {
$icon = $('<img>').attr({src: Ox.UI.getImageURL(
'symbol' + (expanded ? 'Down' : 'Right')
)});
}
}
return $icon;
}
2011-04-22 22:03:10 +00:00
function getItemById(id, items, level) {
var ret = null;
items = items || self.options.items;
level = level || 0;
2011-04-22 22:03:10 +00:00
Ox.forEach(items, function(item) {
if (item.id == id) {
ret = Ox.extend(item, {
2011-04-22 22:03:10 +00:00
level: level
});
2012-05-25 07:46:34 +00:00
Ox.Break();
2011-04-22 22:03:10 +00:00
}
if (item.items) {
ret = getItemById(id, item.items, level + 1);
if (ret) {
2012-05-25 07:46:34 +00:00
Ox.Break();
2011-04-22 22:03:10 +00:00
}
}
});
return ret;
}
2011-12-29 12:24:29 +00:00
function getParent(id, items) {
var ret;
Ox.forEach(items, function(item) {
2012-04-09 08:41:06 +00:00
if (item.items) {
if (Ox.getObjectById(item.items, id)) {
2011-12-29 12:24:29 +00:00
ret = item.id;
} else {
ret = getParent(id, item.items);
}
2012-04-09 08:41:06 +00:00
if (ret) {
2012-05-25 07:46:34 +00:00
Ox.Break();
2011-12-29 12:24:29 +00:00
}
}
});
return ret;
}
2011-04-22 22:03:10 +00:00
function parseData(key, value) {
var ret = {
id: Ox.uid().toString(),
2011-07-26 14:36:31 +00:00
title: key.toString() + ': '
2011-04-22 22:03:10 +00:00
},
type = Ox.typeOf(value);
if (type == 'array' || type == 'object') {
2012-06-13 13:53:20 +00:00
ret.expanded = self.options.expanded;
ret.title += Ox.toTitleCase(type)
+ ' <span class="OxLight">[' + Ox.len(value) + ']</span>';
2012-05-30 00:29:38 +00:00
ret.items = type == 'array' ? value.map(function(v, i) {
2012-05-30 00:32:14 +00:00
return parseData(i, v);
}) : Ox.sort(Object.keys(value)).map(function(k) {
return parseData(k, value[k]);
});
2011-04-22 22:03:10 +00:00
} else {
2011-07-26 14:36:31 +00:00
ret.title += (
type == 'function'
? value.toString().split('{')[0]
: JSON.stringify(value)
.replace(/(^"|"$)/g, '<span class="OxLight">"</span>')
);
2011-04-22 22:03:10 +00:00
}
return ret;
}
function parseItems(items, level) {
var ret = [];
items = items || self.options.items;
level = level || 0;
2011-04-22 22:03:10 +00:00
items.forEach(function(item, i) {
var item_ = Ox.extend({
2011-04-22 22:03:10 +00:00
level: level
}, item, item.items
? {
items: !!item.expanded
? parseItems(item.items, level + 1)
: []
}
: {}
);
2011-04-22 22:03:10 +00:00
ret.push(item_);
2012-05-24 07:45:33 +00:00
if (item.items) {
ret = ret.concat(item_.items);
}
2011-04-22 22:03:10 +00:00
});
return ret;
}
2011-12-29 12:24:29 +00:00
function selectItem(data) {
2012-04-09 08:41:06 +00:00
var id = data.ids[0], parent = id, parents = [];
while (parent = getParent(parent, self.options.items)) {
2011-12-29 12:24:29 +00:00
parents.push(parent);
}
parents = parents.reverse();
toggleItems({
expanded: true,
ids: parents
});
2012-04-09 08:41:06 +00:00
self.$list.options({selected: data.ids})
2011-12-29 12:24:29 +00:00
}
2012-04-09 08:41:06 +00:00
2011-04-22 22:03:10 +00:00
function toggleItem(item, expanded) {
var $img, pos;
2011-04-22 22:03:10 +00:00
item.expanded = expanded;
that.find('.OxItem').each(function() {
var $item = $(this);
2011-04-22 22:03:10 +00:00
if ($item.data('id') == item.id) {
$img = $item.find('.OxToggle');
2011-04-22 22:03:10 +00:00
pos = $item.data('position');
return false;
}
});
//that.$element.value(item.id, 'expanded', expanded);
2011-04-22 22:03:10 +00:00
$img.attr({
2012-06-12 11:13:23 +00:00
src: getIcon(item.id, expanded).attr('src')
2011-04-22 22:03:10 +00:00
});
expanded
? that.$element.addItems(
pos + 1, parseItems(item.items, item.level + 1)
)
: that.$element.removeItems(
pos + 1, parseItems(item.items, item.level + 1).length
);
2011-04-22 22:03:10 +00:00
}
function toggleItems(data) {
2011-04-22 22:03:10 +00:00
data.ids.forEach(function(id, i) {
var item = getItemById(id);
if (item.items && data.expanded != !!item.expanded) {
toggleItem(item, data.expanded);
}
});
}
2012-05-21 10:38:18 +00:00
/*@
gainFocus <f> gainFocus
@*/
that.gainFocus = function() {
self.$list.gainFocus();
return that;
};
2012-05-21 10:38:18 +00:00
/*@
hasFocus <f> hasFocus
@*/
that.hasFocus = function() {
return self.$list.hasFocus();
};
2012-05-21 10:38:18 +00:00
/*@
loseFocus <f> loseFocus
@*/
that.loseFocus = function() {
self.$list.loseFocus();
return that;
};
2011-04-22 22:03:10 +00:00
return that;
2011-11-03 15:42:41 +00:00
2011-04-22 22:03:10 +00:00
};