diff --git a/demos/mouse/js/mouse.js b/demos/mouse/js/mouse.js index 2eb4c03f..bc3b2051 100644 --- a/demos/mouse/js/mouse.js +++ b/demos/mouse/js/mouse.js @@ -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(); diff --git a/source/Ox.UI/js/Core/Ox.Container.js b/source/Ox.UI/js/Core/Ox.Container.js index 2092dde3..1b616955 100644 --- a/source/Ox.UI/js/Core/Ox.Container.js +++ b/source/Ox.UI/js/Core/Ox.Container.js @@ -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); diff --git a/source/Ox.UI/js/Core/Ox.Element.js b/source/Ox.UI/js/Core/Ox.Element.js index 78a567f5..9933a6d5 100644 --- a/source/Ox.UI/js/Core/Ox.Element.js +++ b/source/Ox.UI/js/Core/Ox.Element.js @@ -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); } diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index f52a163e..35213c2c 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -9,7 +9,7 @@ Ox.List List Element centered if true, and orientation is 'horizontal', then keep the selected item centered construct (data) returns the list item HTML - draggable true if the items can be reordered + draggable If true, items can be dragged format <[]> ??? itemHeight item height items list of items, @@ -17,13 +17,13 @@ Ox.List List Element (data, callback) returns [items] itemWidth item width keys keys of the list items - max max number of items that can be selected - min min number of items that must be selected + max Maximum number of items that can be selected (-1 for all) + min Minimum number of items that must be selected orientation 'horizontal' or 'vertical' pageLength number of items per page selected ids of the selected elements sort sort order - sortable + sortable If true, items can be re-ordered type unique name of the key that acts as unique id self 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 })); diff --git a/source/Ox.UI/js/List/Ox.ListItem.js b/source/Ox.UI/js/List/Ox.ListItem.js index d639e389..d00d13d8 100644 --- a/source/Ox.UI/js/List/Ox.ListItem.js +++ b/source/Ox.UI/js/List/Ox.ListItem.js @@ -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 diff --git a/source/Ox.UI/js/List/Ox.TextList.js b/source/Ox.UI/js/List/Ox.TextList.js index 1bc62239..96eaf1ee 100644 --- a/source/Ox.UI/js/List/Ox.TextList.js +++ b/source/Ox.UI/js/List/Ox.TextList.js @@ -27,12 +27,13 @@ Ox.TextList TextList Object draggable If true, items can be dragged id items function() {} {sort, range, keys, callback} or array - max - min + max Maximum number of items that can be selected (-1 for all) + min Minimum number of items that must be selected pageLength scrollbarVisible selected sort + sortable If true, elements can be re-ordered self 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)]; diff --git a/source/Ox.UI/js/Window/Ox.Tooltip.js b/source/Ox.UI/js/Window/Ox.Tooltip.js index 3bc2a886..9f20a539 100644 --- a/source/Ox.UI/js/Window/Ox.Tooltip.js +++ b/source/Ox.UI/js/Window/Ox.Tooltip.js @@ -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' diff --git a/source/Ox.UI/themes/modern/css/modern.css b/source/Ox.UI/themes/modern/css/modern.css index 19256b6b..d4312f60 100644 --- a/source/Ox.UI/themes/modern/css/modern.css +++ b/source/Ox.UI/themes/modern/css/modern.css @@ -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 {