1
0
Fork 0
forked from 0x2620/oxjs

use new-style mouse events in Ox.List

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

View file

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

View file

@ -17,7 +17,11 @@ Ox.Container = function(options, self) {
var that = Ox.Element({}, self) var that = Ox.Element({}, self)
.options(options || {}) .options(options || {})
.addClass('OxContainer'); .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 || {}) .options(options || {})
.addClass('OxContent') .addClass('OxContent')
.appendTo(that); .appendTo(that);

View file

@ -104,7 +104,7 @@ Ox.Element = function(options, self) {
function bind(action, event, fn) { function bind(action, event, fn) {
self.$eventHandler[action]('ox_' + event, function(event, data) { self.$eventHandler[action]('ox_' + event, function(event, data) {
// fixme: remove second parameter // fixme: remove second parameter (legacy)
fn(Ox.extend({ fn(Ox.extend({
_element: that.$element, _element: that.$element,
_event: event _event: event
@ -147,6 +147,10 @@ Ox.Element = function(options, self) {
clientX = e.clientX; clientX = e.clientX;
clientY = e.clientY; clientY = e.clientY;
that.triggerEvent('dragstart', e); that.triggerEvent('dragstart', e);
$('*').bind({
mouseenter: dragenter,
mouseleave: dragleave
});
mouserepeat(); mouserepeat();
mouseInterval = setInterval(mouserepeat, 50); mouseInterval = setInterval(mouserepeat, 50);
Ox.UI.$window.unbind('mouseup', mouseup) Ox.UI.$window.unbind('mouseup', mouseup)
@ -155,6 +159,10 @@ Ox.Element = function(options, self) {
clearInterval(mouseInterval); clearInterval(mouseInterval);
clearTimeout(dragTimeout); clearTimeout(dragTimeout);
Ox.UI.$window.unbind('mousemove', mousemove); Ox.UI.$window.unbind('mousemove', mousemove);
$('*').unbind({
mouseenter: dragenter,
mouseleave: dragleave
});
that.triggerEvent('dragend', extend(e)); that.triggerEvent('dragend', extend(e));
}); });
that.one('mouseleave', function() { that.one('mouseleave', function() {
@ -169,6 +177,12 @@ Ox.Element = function(options, self) {
that.triggerEvent('doubleclick', e); that.triggerEvent('doubleclick', e);
} }
Ox.UI.$window.one('mouseup', mouseup); Ox.UI.$window.one('mouseup', mouseup);
function dragenter(e) {
that.triggerEvent('dragenter', e);
}
function dragleave(e) {
that.triggerEvent('dragleave', e);
}
function extend(e) { function extend(e) {
return Ox.extend({ return Ox.extend({
clientDX: e.clientX - clientX, clientDX: e.clientX - clientX,
@ -336,7 +350,9 @@ Ox.Element = function(options, self) {
Ox.forEach(Ox.makeObject(arguments), function(data, event) { Ox.forEach(Ox.makeObject(arguments), function(data, event) {
if ([ if ([
'mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick', '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) { ].indexOf(event) == -1) {
Ox.print(that.id, self.options.id, 'trigger', event, data); 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', centered <b|false> if true, and orientation is 'horizontal',
then keep the selected item centered then keep the selected item centered
construct <f|null> (data) returns the list item HTML 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 <[]> ??? format <[]> ???
itemHeight <n|16> item height itemHeight <n|16> item height
items <a|f|null> <a> list of items, items <a|f|null> <a> list of items,
@ -17,13 +17,13 @@ Ox.List <f:Ox.Element> List Element
(data, callback) returns [items] (data, callback) returns [items]
itemWidth <n|16> item width itemWidth <n|16> item width
keys <a|[]> keys of the list items keys <a|[]> keys of the list items
max <n|-1> max number of items that can be selected max <n|-1> Maximum number of items that can be selected (-1 for all)
min <n|0> min number of items that must be selected min <n|0> Minimum number of items that must be selected
orientation <s|vertical> 'horizontal' or 'vertical' orientation <s|vertical> 'horizontal' or 'vertical'
pageLength <n|100> number of items per page pageLength <n|100> number of items per page
selected <a|[]> ids of the selected elements selected <a|[]> ids of the selected elements
sort <a|[]> sort order sort <a|[]> sort order
sortable <b|false> sortable <b|false> If true, items can be re-ordered
type <s|text> type <s|text>
unique <s|''> name of the key that acts as unique id unique <s|''> name of the key that acts as unique id
self <o> shared private variable self <o> shared private variable
@ -65,23 +65,29 @@ Ox.List = function(options, self) {
.options(options || {}) .options(options || {})
.scroll(scroll); .scroll(scroll);
// fixme: in short icon lists, we would want to use that.$element (i.e. that), //that.$content.mousedown(_mousedown);
// 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.bindEvent('doubleclick', function() {alert('d')}) that.$content.bindEvent({
/*
that.$content.bindEvent({ // fixme: port to new Ox mouse events
mousedown: mousedown, mousedown: mousedown,
singleclick: singleclick, singleclick: singleclick,
doubleclick: doubleclick, doubleclick: doubleclick
});
if (self.options.draggable) {
that.$content.bindEvent({
dragstart: dragstart, dragstart: dragstart,
drag: drag, drag: drag,
dragenter: dragenter,
dragleave: dragleave,
dragend: dragend 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 // fixme: without this, horizontal lists don't get their full width
self.options.orientation == 'horizontal' && that.$content.css({height: '1px'}); self.options.orientation == 'horizontal' && that.$content.css({height: '1px'});
@ -89,8 +95,6 @@ Ox.List = function(options, self) {
$.extend(self, { $.extend(self, {
$items: [], $items: [],
$pages: [], $pages: [],
clickTimeout: 0,
dragTimeout: 0,
format: {}, format: {},
isAsync: Ox.isFunction(self.options.items), 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 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 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) { if (!self.isAsync) {
self.listLength = self.options.items.length; self.listLength = self.options.items.length;
@ -331,98 +325,74 @@ Ox.List = function(options, self) {
} }
} }
function dragstart(event, e) { // fixme: doesn't work yet function dragstart(event, e) {
if ($(e.target).is('.OxTarget')) {
self.drag = { self.drag = {
pos: findItemPosition(e) ids: self.options.selected
};
$.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',
});
} }
// fixme: shouldn't the target have been
function drag(event, e) { // fixme: doesn't work yet // automatically passed already, somewhere?
var clientY = e.clientY - that.offset()['top'], that.triggerEvent('draganddropstart', {
offset = clientY % 16, ids: self.drag.ids,
position = Ox.limit(parseInt(clientY / 16), 0, self.$items.length - 1); _event: e
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 dragend(event, e) { // fixme: doesn't work yet function drag(event, e) {
var $item = self.$items[self.drag.pos]; if (self.drag) {
$item.removeClass('OxDrag') that.triggerEvent('draganddrop', {
.css({ ids: self.drag.ids,
cursor: 'default', _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) { function dragenter(event, e) {
var $item = self.$items[pos], if (self.drag) {
id = self.$items[pos].options('data')[self.options.unique], that.triggerEvent('draganddropenter', {
startPos = pos, ids: self.drag.ids,
startY = e.clientY, _event: e
stopPos = startPos,
offsets = $.map(self.$items, function($item, pos) {
return (pos - startPos) * 16 - e.offsetY + 8;
}); });
//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) { function dragleave(event, e) {
var $item = self.$items[pos]; if (self.drag) {
$item.removeClass('OxDrag') that.triggerEvent('draganddropleave', {
.css({ ids: self.drag.ids,
cursor: 'default', _event: e
}); });
that.triggerEvent('move', { }
//id: id, }
ids: $.map(self.$items, function($item) {
return $item.options('data')[self.options.unique]; function dragenter(event, e) {
}) if (self.drag) {
//position: pos that.triggerEvent('draganddropenter', {
ids: self.drag.ids,
_event: e
}); });
} }
}
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() { function emptyFirstPage() {
if (self.$pages[0]) { if (self.$pages[0]) {
@ -696,7 +666,6 @@ Ox.List = function(options, self) {
self.$items[pos] = Ox.ListItem({ self.$items[pos] = Ox.ListItem({
construct: self.options.construct, construct: self.options.construct,
data: item, data: item,
draggable: self.options.draggable,
position: pos, position: pos,
unique: self.options.unique unique: self.options.unique
}); });
@ -734,7 +703,6 @@ Ox.List = function(options, self) {
self.$items[pos] = Ox.ListItem({ self.$items[pos] = Ox.ListItem({
construct: self.options.construct, construct: self.options.construct,
data: v, data: v,
draggable: self.options.draggable,
//format: self.options.format, //format: self.options.format,
position: pos, position: pos,
unique: self.options.unique unique: self.options.unique
@ -776,7 +744,7 @@ Ox.List = function(options, self) {
loadPage(page + 1, fn); loadPage(page + 1, fn);
} }
function mousedown(event, e) { // fixme: doesn't work yet function mousedown(event, e) {
var pos = findItemPosition(e); var pos = findItemPosition(e);
self.hadFocus = that.hasFocus(); self.hadFocus = that.hasFocus();
that.gainFocus(); 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, // these can't trigger on mousedown,
// since it could be a doubleclick // since it could be a doubleclick
var pos = findItemPosition(e), var pos = findItemPosition(e),
clickable, editable; clickable, editable;
alert('singleclick') //alert('singleclick')
if (pos > -1) { if (pos > -1) {
if (!e.metaKey && !e.shiftKey && isSelected(pos)) { if (!e.metaKey && !e.shiftKey && isSelected(pos)) {
alert('??') //alert('??')
if (self.selected.length > 1) { if (self.selected.length > 1) {
// click on one of multiple selected items // click on one of multiple selected items
alert('!!') //alert('!!')
select(pos); select(pos);
} else if (self.options.type == 'text' && self.hadFocus) { } else if (self.options.type == 'text' && self.hadFocus) {
$cell = findCell(e); $cell = findCell(e);
@ -832,12 +848,11 @@ Ox.List = function(options, self) {
} }
} }
function doubleclick(event, e) { // fixme: doesn't work yet function doubleclick(event, e) {
alert('doubleclick')
open(); open();
} }
function _mousedown(e) { function _mousedown(e) { // fixme: no longer used, remove
var pos = findItemPosition(e), var pos = findItemPosition(e),
clickable, editable, clickable, editable,
clickTimeout = false, clickTimeout = false,
@ -1376,7 +1391,6 @@ Ox.List = function(options, self) {
$items.push($item = Ox.ListItem({ $items.push($item = Ox.ListItem({
construct: self.options.construct, construct: self.options.construct,
data: item, data: item,
draggable: self.options.draggable,
position: pos + i, position: pos + i,
unique: self.options.unique unique: self.options.unique
})); }));

View file

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

View file

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

View file

@ -362,18 +362,20 @@ Lists
.OxThemeModern .OxTextList .OxFocus .OxItem.OxSelected:nth-child(even) { .OxThemeModern .OxTextList .OxFocus .OxItem.OxSelected:nth-child(even) {
background: rgb(66, 66, 66); 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); 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); 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 { .OxThemeModern .OxTextList .OxBar .OxSelected {