use new-style mouse events in Ox.List

This commit is contained in:
rlx 2011-09-03 23:04:18 +00:00
parent 2043dc7a12
commit be3b1d573d
8 changed files with 185 additions and 143 deletions

View file

@ -36,7 +36,7 @@ Ox.load('UI', {
.appendTo(Ox.UI.$body);
[
'anyclick', 'singleclick', 'doubleclick', 'mouserepeat',
'dragstart', 'drag', 'dragpause', 'dragend'
'dragstart', 'drag', 'dragenter', 'dragleave', 'dragpause', 'dragend'
].forEach(function(event) {
$target.bindEvent(event, function(e) {
var date = new Date();

View file

@ -17,7 +17,11 @@ Ox.Container = function(options, self) {
var that = Ox.Element({}, self)
.options(options || {})
.addClass('OxContainer');
that.$content = Ox.Element({}, self) // fixme: passing self twice??
// fixme: we used to pass self _again_ to the content,
// which obviously makes clicks trigger twice
// removed for now, but may break something else.
// (maybe, if needed, content can pass a container event along)
that.$content = Ox.Element({})
.options(options || {})
.addClass('OxContent')
.appendTo(that);

View file

@ -104,7 +104,7 @@ Ox.Element = function(options, self) {
function bind(action, event, fn) {
self.$eventHandler[action]('ox_' + event, function(event, data) {
// fixme: remove second parameter
// fixme: remove second parameter (legacy)
fn(Ox.extend({
_element: that.$element,
_event: event
@ -147,14 +147,22 @@ Ox.Element = function(options, self) {
clientX = e.clientX;
clientY = e.clientY;
that.triggerEvent('dragstart', e);
$('*').bind({
mouseenter: dragenter,
mouseleave: dragleave
});
mouserepeat();
mouseInterval = setInterval(mouserepeat, 50);
Ox.UI.$window.unbind('mouseup', mouseup)
.mousemove(mousemove)
.one('mouseup', function(e) {
clearInterval(mouseInterval);
clearTimeout(dragTimeout);
clearTimeout(dragTimeout);
Ox.UI.$window.unbind('mousemove', mousemove);
$('*').unbind({
mouseenter: dragenter,
mouseleave: dragleave
});
that.triggerEvent('dragend', extend(e));
});
that.one('mouseleave', function() {
@ -169,6 +177,12 @@ Ox.Element = function(options, self) {
that.triggerEvent('doubleclick', e);
}
Ox.UI.$window.one('mouseup', mouseup);
function dragenter(e) {
that.triggerEvent('dragenter', e);
}
function dragleave(e) {
that.triggerEvent('dragleave', e);
}
function extend(e) {
return Ox.extend({
clientDX: e.clientX - clientX,
@ -336,7 +350,9 @@ Ox.Element = function(options, self) {
Ox.forEach(Ox.makeObject(arguments), function(data, event) {
if ([
'mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick',
'dragstart', 'drag', 'dragpause', 'dragend', 'playing', 'position', 'progress'
'dragstart', 'drag', 'dragenter', 'dragleave', 'dragpause', 'dragend',
'draganddropstart', 'draganddrop', 'draganddropenter', 'draganddropleave', 'draganddropend',
'playing', 'position', 'progress'
].indexOf(event) == -1) {
Ox.print(that.id, self.options.id, 'trigger', event, data);
}

View file

@ -9,7 +9,7 @@ Ox.List <f:Ox.Element> List Element
centered <b|false> if true, and orientation is 'horizontal',
then keep the selected item centered
construct <f|null> (data) returns the list item HTML
draggable <b|false> true if the items can be reordered
draggable <b|false> If true, items can be dragged
format <[]> ???
itemHeight <n|16> item height
items <a|f|null> <a> list of items,
@ -17,13 +17,13 @@ Ox.List <f:Ox.Element> List Element
(data, callback) returns [items]
itemWidth <n|16> item width
keys <a|[]> keys of the list items
max <n|-1> max number of items that can be selected
min <n|0> min number of items that must be selected
max <n|-1> Maximum number of items that can be selected (-1 for all)
min <n|0> Minimum number of items that must be selected
orientation <s|vertical> 'horizontal' or 'vertical'
pageLength <n|100> number of items per page
selected <a|[]> ids of the selected elements
sort <a|[]> sort order
sortable <b|false>
sortable <b|false> If true, items can be re-ordered
type <s|text>
unique <s|''> name of the key that acts as unique id
self <o> shared private variable
@ -65,23 +65,29 @@ Ox.List = function(options, self) {
.options(options || {})
.scroll(scroll);
// fixme: in short icon lists, we would want to use that.$element (i.e. that),
// to deselect by clicking below the items
// but clicking on the scrollbar then causes weird selections
// ... we need something analogous to fillFirstPage for icon lists
that.$content.mousedown(_mousedown);
//that.$content.mousedown(_mousedown);
//that.bindEvent('doubleclick', function() {alert('d')})
/*
that.$content.bindEvent({ // fixme: port to new Ox mouse events
that.$content.bindEvent({
mousedown: mousedown,
singleclick: singleclick,
doubleclick: doubleclick,
dragstart: dragstart,
drag: drag,
dragend: dragend
doubleclick: doubleclick
});
*/
if (self.options.draggable) {
that.$content.bindEvent({
dragstart: dragstart,
drag: drag,
dragenter: dragenter,
dragleave: dragleave,
dragend: dragend
});
} else if (self.options.sortable) {
that.$content.bindEvent({
dragstart: movestart,
drag: move,
dragend: moveend
});
}
// fixme: without this, horizontal lists don't get their full width
self.options.orientation == 'horizontal' && that.$content.css({height: '1px'});
@ -89,8 +95,6 @@ Ox.List = function(options, self) {
$.extend(self, {
$items: [],
$pages: [],
clickTimeout: 0,
dragTimeout: 0,
format: {},
isAsync: Ox.isFunction(self.options.items),
itemMargin: self.options.type == 'text' ? 0 : 8, // 2 x 4 px margin ... fixme: the 2x should be computed later
@ -170,16 +174,6 @@ Ox.List = function(options, self) {
66, 60, 65, 70, 60, 64, 68, 72, 76, 60
];
}
/*
if (self.options.draggable) {
that.bind({
dragstart: function(e) {
//alert('DRAGSTART')
Ox.print('DRAGSTART', e);
}
});
}
*/
if (!self.isAsync) {
self.listLength = self.options.items.length;
@ -331,97 +325,73 @@ Ox.List = function(options, self) {
}
}
function dragstart(event, e) { // fixme: doesn't work yet
self.drag = {
pos: findItemPosition(e)
};
$.extend(self.drag, {
id: self.$items[self.drag.pos].options('data')[self.options.unique],
startPos: self.drag.pos,
startY: e.clientY,
stopPos: self.drag.pos
});
self.$items[pos].addClass('OxDrag') // fixme: why does the class not work?
.css({
cursor: 'move',
function dragstart(event, e) {
if ($(e.target).is('.OxTarget')) {
self.drag = {
ids: self.options.selected
}
// fixme: shouldn't the target have been
// automatically passed already, somewhere?
that.triggerEvent('draganddropstart', {
ids: self.drag.ids,
_event: e
});
}
function drag(event, e) { // fixme: doesn't work yet
var clientY = e.clientY - that.offset()['top'],
offset = clientY % 16,
position = Ox.limit(parseInt(clientY / 16), 0, self.$items.length - 1);
if (position < self.drag.pos) {
self.drag.stopPos = position + (offset > 8 ? 1 : 0);
} else if (position > self.drag.pos) {
self.drag.stopPos = position - (offset <= 8 ? 1 : 0);
}
if (self.drag.stopPos != self.drag.pos) {
moveItem(self.drag.pos, self.drag.stopPos);
self.drag.pos = self.drag.stopPos;
}
function drag(event, e) {
if (self.drag) {
that.triggerEvent('draganddrop', {
ids: self.drag.ids,
_event: e
});
}
}
function dragend(event, e) { // fixme: doesn't work yet
var $item = self.$items[self.drag.pos];
$item.removeClass('OxDrag')
.css({
cursor: 'default',
function dragenter(event, e) {
if (self.drag) {
that.triggerEvent('draganddropenter', {
ids: self.drag.ids,
_event: e
});
that.triggerEvent('move', {
//id: id,
ids: $.map(self.$items, function($item) {
return $item.options('data')[self.options.unique];
})
//position: pos
});
}
}
function dragItem(pos, e) {
var $item = self.$items[pos],
id = self.$items[pos].options('data')[self.options.unique],
startPos = pos,
startY = e.clientY,
stopPos = startPos,
offsets = $.map(self.$items, function($item, pos) {
return (pos - startPos) * 16 - e.offsetY + 8;
function dragleave(event, e) {
if (self.drag) {
that.triggerEvent('draganddropleave', {
ids: self.drag.ids,
_event: e
});
//Ox.print('dragItem', e);
//Ox.print(e.offsetY, offsets)
$item.addClass('OxDrag');
Ox.UI.$window.mousemove(function(e) {
var clientY = e.clientY - that.offset()['top'],
offset = clientY % 16,
position = Ox.limit(parseInt(clientY / 16), 0, self.$items.length - 1);
if (position < pos) {
stopPos = position + (offset > 8 ? 1 : 0);
} else if (position > pos) {
stopPos = position - (offset <= 8 ? 1 : 0);
}
if (stopPos != pos) {
moveItem(pos, stopPos);
pos = stopPos;
}
});
Ox.UI.$window.one('mouseup', function() {
dropItem(id, pos);
Ox.UI.$window.unbind('mousemove');
});
}
}
function dropItem(id, pos) {
var $item = self.$items[pos];
$item.removeClass('OxDrag')
.css({
cursor: 'default',
function dragenter(event, e) {
if (self.drag) {
that.triggerEvent('draganddropenter', {
ids: self.drag.ids,
_event: e
});
that.triggerEvent('move', {
//id: id,
ids: $.map(self.$items, function($item) {
return $item.options('data')[self.options.unique];
})
//position: pos
});
}
}
function dragleave(event, e) {
if (self.drag) {
that.triggerEvent('draganddropleave', {
ids: self.drag.ids,
_event: e
});
}
}
function dragend(event, e) {
if (self.drag) {
that.triggerEvent('draganddropend', {
ids: self.drag.ids,
_event: e
});
delete self.drag;
}
}
function emptyFirstPage() {
@ -696,7 +666,6 @@ Ox.List = function(options, self) {
self.$items[pos] = Ox.ListItem({
construct: self.options.construct,
data: item,
draggable: self.options.draggable,
position: pos,
unique: self.options.unique
});
@ -734,7 +703,6 @@ Ox.List = function(options, self) {
self.$items[pos] = Ox.ListItem({
construct: self.options.construct,
data: v,
draggable: self.options.draggable,
//format: self.options.format,
position: pos,
unique: self.options.unique
@ -776,7 +744,7 @@ Ox.List = function(options, self) {
loadPage(page + 1, fn);
}
function mousedown(event, e) { // fixme: doesn't work yet
function mousedown(event, e) {
var pos = findItemPosition(e);
self.hadFocus = that.hasFocus();
that.gainFocus();
@ -804,18 +772,66 @@ Ox.List = function(options, self) {
}
}
function singleclick(event, e) { // fixme: doesn't work yet
function movestart(event, e) {
self.drag = {
pos: findItemPosition(e)
};
$.extend(self.drag, {
id: self.$items[self.drag.pos].options('data')[self.options.unique],
startPos: self.drag.pos,
startY: e.clientY,
stopPos: self.drag.pos
});
self.$items[self.drag.pos]
.addClass('OxDrag')
.css({
cursor: 'move',
});
}
function move(event, e) {
var clientY = e.clientY - that.offset()['top'],
offset = clientY % 16,
position = Ox.limit(parseInt(clientY / 16), 0, self.$items.length - 1);
if (position < self.drag.pos) {
self.drag.stopPos = position + (offset > 8 ? 1 : 0);
} else if (position > self.drag.pos) {
self.drag.stopPos = position - (offset <= 8 ? 1 : 0);
}
if (self.drag.stopPos != self.drag.pos) {
moveItem(self.drag.pos, self.drag.stopPos);
self.drag.pos = self.drag.stopPos;
}
}
function moveend(event, e) {
var $item = self.$items[self.drag.pos];
$item.removeClass('OxDrag')
.css({
cursor: 'default',
});
that.triggerEvent('move', {
//id: id,
ids: $.map(self.$items, function($item) {
return $item.options('data')[self.options.unique];
})
//position: pos
});
delete self.drag;
}
function singleclick(event, e) {
// these can't trigger on mousedown,
// since it could be a doubleclick
var pos = findItemPosition(e),
clickable, editable;
alert('singleclick')
//alert('singleclick')
if (pos > -1) {
if (!e.metaKey && !e.shiftKey && isSelected(pos)) {
alert('??')
//alert('??')
if (self.selected.length > 1) {
// click on one of multiple selected items
alert('!!')
//alert('!!')
select(pos);
} else if (self.options.type == 'text' && self.hadFocus) {
$cell = findCell(e);
@ -832,12 +848,11 @@ Ox.List = function(options, self) {
}
}
function doubleclick(event, e) { // fixme: doesn't work yet
alert('doubleclick')
function doubleclick(event, e) {
open();
}
function _mousedown(e) {
function _mousedown(e) { // fixme: no longer used, remove
var pos = findItemPosition(e),
clickable, editable,
clickTimeout = false,
@ -1376,7 +1391,6 @@ Ox.List = function(options, self) {
$items.push($item = Ox.ListItem({
construct: self.options.construct,
data: item,
draggable: self.options.draggable,
position: pos + i,
unique: self.options.unique
}));

View file

@ -34,9 +34,6 @@ Ox.ListItem = function(options, self) {
function constructItem(update) {
var $element = self.options.construct(self.options.data)
.addClass('OxItem')
.attr({
draggable: self.options.draggable
})
.data({
id: self.options.data[self.options.unique],
position: self.options.position

View file

@ -27,12 +27,13 @@ Ox.TextList <f:Ox.Element> TextList Object
draggable <b|false> If true, items can be dragged
id <s|''>
items <f|null> function() {} {sort, range, keys, callback} or array
max <n|-1>
min <n|0>
max <n|-1> Maximum number of items that can be selected (-1 for all)
min <n|0> Minimum number of items that must be selected
pageLength <n|100>
scrollbarVisible <b|false>
selected <a|[]>
sort <a|[]>
sortable <b|false> If true, elements can be re-ordered
self <o> shared private variable
@*/
@ -57,7 +58,8 @@ Ox.TextList = function(options, self) {
pageLength: 100,
scrollbarVisible: false,
selected: [],
sort: []
sort: [],
sortable: false
})
.options(options || {})
.addClass('OxTextList')
@ -859,7 +861,7 @@ Ox.TextList = function(options, self) {
that.value = function(id, key, value) {
// fixme: make this accept id, {k: v, ...}
Ox.print('value', id, key, value)
//Ox.print('value', id, key, value)
var $cell,
$item = getItem(id);
//column = self.options.columns[getColumnIndexById(key)];

View file

@ -52,15 +52,22 @@ Ox.Tooltip = function(options, self) {
var left, top, width, height;
if (self.options.title) {
if (arguments.length == 1) {
y = arguments[0].clientY;
x = arguments[0].clientX;
self.x = arguments[0].clientX;
self.y = arguments[0].clientY;
} else if (arguments.length == 2) {
self.x = x;
self.y = y
}
$('.OxTooltip').remove(); // fixme: don't use DOM
that.appendTo(Ox.UI.$body);
width = that.width();
height = that.height();
left = Ox.limit(x - width / 2, 0, window.innerWidth - width);
top = y > window.innerHeight - height - 16 ? y - 16 - height : y + 16;
left = Ox.limit(
self.x - width / 2, 0, window.innerWidth - width
);
top = self.y > window.innerHeight - height - 16
? self.y - 16 - height
: self.y + 16;
that.css({
left: left + 'px',
top: top + 'px'

View file

@ -362,18 +362,20 @@ Lists
.OxThemeModern .OxTextList .OxFocus .OxItem.OxSelected:nth-child(even) {
background: rgb(66, 66, 66);
}
.OxThemeModern .OxTextList .OxItem.OxDrop:nth-child(odd) .OxCell {
.OxThemeModern .OxTextList .OxItem.OxDroppable:nth-child(odd) .OxCell {
//background: rgb(62, 62, 78);
}
.OxThemeModern .OxTextList .OxItem.OxDroppable:nth-child(even) .OxCell {
//background: rgb(66, 66, 82);
}
.OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(odd) .OxCell {
background: rgb(78, 78, 94);
background: rgb(78, 78, 78);
}
.OxThemeModern .OxTextList .OxItem.OxDrop:nth-child(even) .OxCell {
.OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(even) .OxCell {
background: rgb(82, 82, 98);
background: rgb(82, 82, 82);
}
.OxThemeModern .OxTextList .OxItem.OxDragover:nth-child(odd) .OxCell {
background: rgb(94, 94, 94);
}
.OxThemeModern .OxTextList .OxItem.OxDragover:nth-child(even) .OxCell {
background: rgb(98, 98, 98);
}
.OxThemeModern .OxTextList .OxBar .OxSelected {