2011-07-29 18:48:43 +00:00
|
|
|
// vim: et:ts=4:sw=4:sts=4:ft=javascript
|
2011-04-22 22:03:10 +00:00
|
|
|
// check out http://ejohn.org/apps/learn/#36 (-#38, making fns work w/o new)
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
|
|
|
Ox.Element <function:Ox.JQueryElement> Basic UI element object
|
|
|
|
# Usage --------------------------------------------------------------------
|
|
|
|
([options[, self]]) -> <object> UI element
|
|
|
|
# Arguments ----------------------------------------------------------------
|
|
|
|
options <object> the options of the element
|
|
|
|
# Properties
|
|
|
|
element <string> tagname or CSS selector
|
2011-05-17 18:44:53 +00:00
|
|
|
tooltip <string|function> tooltip title or function that returns one
|
|
|
|
(e) -> <string> tooltip title
|
|
|
|
e <object> mouse event
|
2011-05-05 18:02:56 +00:00
|
|
|
options <string> tagname or CSS selector
|
|
|
|
self <object> shared private variable
|
|
|
|
# Events -------------------------------------------------------------------
|
|
|
|
anyclick <event> anyclick
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires on mouseup, but not on any subsequent mouseup within 250 ms
|
2011-05-05 18:02:56 +00:00
|
|
|
* <*> original event properties
|
|
|
|
doubleclick <event> doubleclick
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires on the second mousedown within 250 ms
|
2011-05-05 18:02:56 +00:00
|
|
|
* <*> original event properties
|
|
|
|
drag <event> drag
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires on mousemove after dragstart, stops firing on mouseup
|
2011-05-05 18:02:56 +00:00
|
|
|
clientDX <number> horizontal drag delta in px
|
|
|
|
clientDY <number> vertical drag delta in px
|
|
|
|
* <*> original event properties
|
|
|
|
dragend <event> dragpause
|
|
|
|
Fires on mouseup after dragstart
|
|
|
|
clientDX <number> horizontal drag delta in px
|
|
|
|
clientDY <number> vertical drag delta in px
|
|
|
|
* <*> original event properties
|
2011-09-04 12:19:36 +00:00
|
|
|
dragenter <event> dragenter
|
|
|
|
Fires when entering an element during drag
|
|
|
|
dragleave <event> dragleave
|
|
|
|
Fires when leaving an element during drag
|
2011-05-05 18:02:56 +00:00
|
|
|
dragpause <event> dragpause
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires once when the mouse doesn't move for 250 ms during drag
|
2011-05-05 18:02:56 +00:00
|
|
|
clientDX <number> horizontal drag delta in px
|
|
|
|
clientDY <number> vertical drag delta in px
|
|
|
|
* <*> original event properties
|
|
|
|
dragstart <event> dragstart
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires when the mouse is down for 250 ms
|
2011-05-05 18:02:56 +00:00
|
|
|
* <*> original event properties
|
|
|
|
mouserepeat <event> mouserepeat
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires every 50 ms after the mouse was down for 250 ms, stops firing on
|
2011-05-05 18:02:56 +00:00
|
|
|
mouseleave or mouseup
|
|
|
|
* <*> original event properties
|
|
|
|
singleclick <event> singleclick
|
2011-09-04 12:19:36 +00:00
|
|
|
Fires 250 ms after mouseup, if there was no subsequent mousedown
|
2011-05-05 18:02:56 +00:00
|
|
|
* <*> original event properties
|
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
Ox.Element = function(options, self) {
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
// create private object
|
2011-04-22 22:03:10 +00:00
|
|
|
self = self || {};
|
2011-04-29 12:40:51 +00:00
|
|
|
// create defaults and options objects
|
|
|
|
self.defaults = {};
|
2011-04-22 22:03:10 +00:00
|
|
|
self.options = options || {};
|
2011-04-29 12:40:51 +00:00
|
|
|
// allow for Ox.TestElement('<tagname>')
|
|
|
|
// or Ox.TestElement('cssSelector')
|
|
|
|
if (Ox.isString(self.options)) {
|
2011-04-22 22:03:10 +00:00
|
|
|
self.options = {
|
|
|
|
element: self.options
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
|
|
|
}
|
2011-04-29 12:40:51 +00:00
|
|
|
// create event handler
|
2011-08-23 19:08:08 +00:00
|
|
|
// (this can be passed as part of self)
|
2011-04-22 22:03:10 +00:00
|
|
|
if (!self.$eventHandler) {
|
|
|
|
self.$eventHandler = $('<div>');
|
|
|
|
}
|
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
// create public object
|
2011-04-22 22:03:10 +00:00
|
|
|
var that = new Ox.JQueryElement(
|
2011-04-29 12:40:51 +00:00
|
|
|
$(self.options.element || '<div>')
|
2011-04-22 22:03:10 +00:00
|
|
|
)
|
|
|
|
.mousedown(mousedown);
|
|
|
|
|
2011-05-17 18:44:53 +00:00
|
|
|
if (self.options.tooltip) {
|
|
|
|
if (Ox.isString(self.options.tooltip)) {
|
|
|
|
that.$tooltip = Ox.Tooltip({
|
|
|
|
title: self.options.tooltip,
|
|
|
|
});
|
|
|
|
that.bind({
|
|
|
|
mouseenter: mouseenter
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
that.$tooltip = Ox.Tooltip({
|
|
|
|
animate: false
|
|
|
|
});
|
|
|
|
that.bind({
|
|
|
|
mousemove: mousemove
|
|
|
|
});
|
|
|
|
}
|
|
|
|
that.bind({
|
|
|
|
mouseleave: mouseleave
|
|
|
|
});
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-04-29 22:07:23 +00:00
|
|
|
function bind(action, event, fn) {
|
|
|
|
self.$eventHandler[action]('ox_' + event, function(event, data) {
|
2011-06-02 03:02:16 +00:00
|
|
|
fn(Ox.extend({
|
|
|
|
_element: that.$element,
|
|
|
|
_event: event
|
2011-09-17 17:39:38 +00:00
|
|
|
}, data));
|
2011-04-29 22:07:23 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
function mousedown(e) {
|
|
|
|
/*
|
|
|
|
better mouse events
|
|
|
|
mousedown:
|
|
|
|
trigger mousedown
|
|
|
|
within 250 msec:
|
|
|
|
mouseup: trigger anyclick ("click" would collide with click events of certain widgets)
|
|
|
|
mouseup + mousedown: trigger doubleclick
|
|
|
|
after 250 msec:
|
|
|
|
mouseup + no mousedown within 250 msec: trigger singleclick
|
|
|
|
no mouseup within 250 msec:
|
|
|
|
trigger mouserepeat every 50 msec
|
|
|
|
trigger dragstart
|
|
|
|
mousemove: trigger drag
|
|
|
|
no mousemove within 250 msec:
|
|
|
|
trigger dragpause
|
|
|
|
mouseup: trigger dragend
|
|
|
|
*/
|
|
|
|
var clientX, clientY,
|
|
|
|
dragTimeout = 0,
|
|
|
|
mouseInterval = 0;
|
|
|
|
if (!self.mouseTimeout) {
|
|
|
|
// first mousedown
|
|
|
|
that.triggerEvent('mousedown', e);
|
|
|
|
self.mouseup = false;
|
|
|
|
self.mouseTimeout = setTimeout(function() {
|
|
|
|
self.mouseTimeout = 0;
|
|
|
|
if (self.mouseup) {
|
|
|
|
// singleclick
|
|
|
|
that.triggerEvent('singleclick', e);
|
|
|
|
} else {
|
|
|
|
// mouserepeat, drag
|
|
|
|
clientX = e.clientX;
|
|
|
|
clientY = e.clientY;
|
|
|
|
that.triggerEvent('dragstart', e);
|
2011-09-03 23:04:18 +00:00
|
|
|
$('*').bind({
|
|
|
|
mouseenter: dragenter,
|
|
|
|
mouseleave: dragleave
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
mouserepeat();
|
|
|
|
mouseInterval = setInterval(mouserepeat, 50);
|
|
|
|
Ox.UI.$window.unbind('mouseup', mouseup)
|
|
|
|
.mousemove(mousemove)
|
|
|
|
.one('mouseup', function(e) {
|
|
|
|
clearInterval(mouseInterval);
|
2011-09-03 23:04:18 +00:00
|
|
|
clearTimeout(dragTimeout);
|
2011-04-22 22:03:10 +00:00
|
|
|
Ox.UI.$window.unbind('mousemove', mousemove);
|
2011-09-03 23:04:18 +00:00
|
|
|
$('*').unbind({
|
|
|
|
mouseenter: dragenter,
|
|
|
|
mouseleave: dragleave
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
that.triggerEvent('dragend', extend(e));
|
|
|
|
});
|
|
|
|
that.one('mouseleave', function() {
|
|
|
|
clearInterval(mouseInterval);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, 250);
|
|
|
|
} else {
|
|
|
|
// second mousedown
|
|
|
|
clearTimeout(self.mouseTimeout);
|
|
|
|
self.mouseTimeout = 0;
|
|
|
|
that.triggerEvent('doubleclick', e);
|
|
|
|
}
|
|
|
|
Ox.UI.$window.one('mouseup', mouseup);
|
2011-09-03 23:04:18 +00:00
|
|
|
function dragenter(e) {
|
|
|
|
that.triggerEvent('dragenter', e);
|
|
|
|
}
|
|
|
|
function dragleave(e) {
|
|
|
|
that.triggerEvent('dragleave', e);
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
function extend(e) {
|
|
|
|
return Ox.extend({
|
|
|
|
clientDX: e.clientX - clientX,
|
|
|
|
clientDY: e.clientY - clientY
|
|
|
|
}, e);
|
|
|
|
}
|
|
|
|
function mousemove(e) {
|
|
|
|
e = extend(e);
|
|
|
|
clearTimeout(dragTimeout);
|
|
|
|
dragTimeout = setTimeout(function() {
|
|
|
|
that.triggerEvent('dragpause', e);
|
|
|
|
}, 250);
|
|
|
|
that.triggerEvent('drag', e);
|
|
|
|
}
|
|
|
|
function mouserepeat() {
|
|
|
|
that.triggerEvent('mouserepeat');
|
|
|
|
}
|
|
|
|
function mouseup(e) {
|
2011-05-05 18:02:56 +00:00
|
|
|
// only trigger on first mouseup
|
2011-04-22 22:03:10 +00:00
|
|
|
if (!self.mouseup) {
|
|
|
|
that.triggerEvent('anyclick', e);
|
|
|
|
self.mouseup = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function mouseenter(e) {
|
2011-05-17 18:44:53 +00:00
|
|
|
that.$tooltip.show(e);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function mouseleave(e) {
|
2011-05-17 18:44:53 +00:00
|
|
|
that.$tooltip.hide();
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function mousemove(e) {
|
2011-08-08 13:58:19 +00:00
|
|
|
//Ox.print('mousemove!!')
|
2011-05-17 18:44:53 +00:00
|
|
|
that.$tooltip.options({
|
|
|
|
title: self.options.tooltip(e)
|
|
|
|
}).show(e);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
self.setOption = function() {
|
|
|
|
// self.setOptions(key, value)
|
2011-04-22 22:03:10 +00:00
|
|
|
// is called when an option changes
|
|
|
|
// (to be implemented by widget)
|
|
|
|
};
|
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
that._self = self; // fixme: remove
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
|
|
|
bindEvent <function> Binds a function to an event
|
2011-05-07 21:07:53 +00:00
|
|
|
(event, callback) -> <o> This element
|
|
|
|
({event: callback, ...}) -> <o> This element
|
2011-05-05 18:02:56 +00:00
|
|
|
callback <f> Callback function
|
2011-05-07 21:07:53 +00:00
|
|
|
data <o> event data (key/value pairs)
|
|
|
|
event <s> Event name
|
|
|
|
Event names can be namespaced, like <code>'click.foo'</code>
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.bindEvent = function() {
|
2011-04-29 22:07:23 +00:00
|
|
|
Ox.forEach(Ox.makeObject(arguments), function(fn, event) {
|
|
|
|
bind('bind', event, fn);
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
|
|
|
}
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
|
|
|
bindEventOnce <function> Binds a function to an event, once
|
2011-05-07 21:07:53 +00:00
|
|
|
(event, callback) -> <obj> This element object
|
|
|
|
({event: callback, ...}) -> <obj> This element object
|
2011-05-05 18:02:56 +00:00
|
|
|
callback <f> Callback function
|
2011-05-07 21:07:53 +00:00
|
|
|
data <o> event data (key/value pairs)
|
|
|
|
event <s> Event name
|
|
|
|
Event names can be namespaced, like <code>'click.foo'</code>
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.bindEventOnce = function() {
|
2011-04-29 22:07:23 +00:00
|
|
|
Ox.forEach(Ox.makeObject(arguments), function(fn, event) {
|
|
|
|
bind('one', event, fn);
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
2011-05-07 21:07:53 +00:00
|
|
|
defaults <function> Sets the default options for an element object
|
|
|
|
({key: value, ...}) -> <obj> This element object
|
|
|
|
key <str> The name of the default option
|
|
|
|
value <val> The value of the default option
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.defaults = function(defaults) {
|
2011-04-29 12:40:51 +00:00
|
|
|
// sets the default options
|
2011-04-22 22:03:10 +00:00
|
|
|
self.defaults = defaults;
|
2011-04-29 12:40:51 +00:00
|
|
|
self.options = defaults;
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
2011-05-07 21:07:53 +00:00
|
|
|
gainFocus <function> Makes an element object gain focus
|
|
|
|
() -> <obj> This element object
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.gainFocus = function() {
|
|
|
|
Ox.Focus.focus(that.id);
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
2011-05-07 21:07:53 +00:00
|
|
|
hasFocus <function> Returns true if an element object has focus
|
|
|
|
() -> <boolean> True if the element has focus
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.hasFocus = function() {
|
|
|
|
return Ox.Focus.focused() == that.id;
|
|
|
|
};
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
2011-05-07 21:07:53 +00:00
|
|
|
loseFocus <function> Makes an element object lose focus
|
|
|
|
() -> <object> This element object
|
2011-05-05 18:02:56 +00:00
|
|
|
@*/
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
that.loseFocus = function() {
|
|
|
|
Ox.Focus.blur(that.id);
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-05 18:02:56 +00:00
|
|
|
/*@
|
2011-05-07 21:07:53 +00:00
|
|
|
options <function> Gets or sets the options of an element object
|
2011-05-05 18:02:56 +00:00
|
|
|
# Usage
|
|
|
|
() -> <obj> all options
|
2011-05-11 16:33:19 +00:00
|
|
|
(key) -> <any> the value of option[key]
|
2011-05-05 18:02:56 +00:00
|
|
|
(key, value) -> <obj> this element
|
2011-05-11 16:33:19 +00:00
|
|
|
Sets options[key] to value and calls self.setOption(key, value)
|
2011-05-05 18:02:56 +00:00
|
|
|
if the key/value pair was added or modified
|
|
|
|
({key: value, ...}) -> <obj> this element
|
2011-05-11 16:33:19 +00:00
|
|
|
Sets multiple options and calls self.setOption(key, value)
|
2011-05-05 18:02:56 +00:00
|
|
|
for every key/value pair that was added or modified
|
|
|
|
# Arguments
|
|
|
|
key <str> the name of the option
|
|
|
|
value <val> the value of the option
|
|
|
|
@*/
|
|
|
|
|
2011-04-29 12:40:51 +00:00
|
|
|
that.options = function() {
|
|
|
|
return Ox.getset(self.options, arguments, self.setOption, that);
|
2011-04-22 22:03:10 +00:00
|
|
|
};
|
|
|
|
|
2011-05-07 21:07:53 +00:00
|
|
|
/*@
|
|
|
|
removeElement <function> Removes an element object and its event handler
|
|
|
|
() -> <obj> This element
|
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.removeElement = function() {
|
|
|
|
that.loseFocus();
|
|
|
|
delete self.$eventHandler;
|
|
|
|
that.remove();
|
2011-08-15 12:18:14 +00:00
|
|
|
// fixme: ok to comment out the following line?
|
2011-04-22 22:03:10 +00:00
|
|
|
delete Ox.UI.elements[that.id];
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-07 21:07:53 +00:00
|
|
|
/*@
|
|
|
|
triggerEvent <function> Triggers an event
|
|
|
|
(event) -> <object> This element object
|
|
|
|
(event, data) -> <object> This element object
|
|
|
|
({event: data, ...}) -> <object> This element object
|
|
|
|
event <string> Event name
|
|
|
|
data <object> Event data (key/value pairs)
|
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.triggerEvent = function() {
|
2011-04-29 22:07:23 +00:00
|
|
|
Ox.forEach(Ox.makeObject(arguments), function(data, event) {
|
|
|
|
if ([
|
|
|
|
'mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick',
|
2011-09-03 23:04:18 +00:00
|
|
|
'dragstart', 'drag', 'dragenter', 'dragleave', 'dragpause', 'dragend',
|
|
|
|
'draganddropstart', 'draganddrop', 'draganddropenter', 'draganddropleave', 'draganddropend',
|
|
|
|
'playing', 'position', 'progress'
|
2011-04-29 22:07:23 +00:00
|
|
|
].indexOf(event) == -1) {
|
|
|
|
Ox.print(that.id, self.options.id, 'trigger', event, data);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
2011-05-30 08:46:12 +00:00
|
|
|
// it is necessary to check if self.$eventHandler exists,
|
|
|
|
// since, for example, when removing the element on click,
|
|
|
|
// singleclick will fire after the removal of the event handler
|
|
|
|
self.$eventHandler && self.$eventHandler.trigger('ox_' + event, data);
|
2011-04-29 22:07:23 +00:00
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-05-07 21:07:53 +00:00
|
|
|
/*@
|
|
|
|
unbindEvent <function> Unbinds all callbacks from an event
|
|
|
|
To unbind a specific handler, use namespaced events, like
|
|
|
|
<code>bindEvent('click.foo', callback)</code>, and then
|
|
|
|
<code>unbindEvent('click.foo')</code>.
|
|
|
|
() -> <object> This element object
|
|
|
|
Unbinds all events
|
|
|
|
(event) -> <object> This element object
|
|
|
|
Unbinds one event
|
|
|
|
(event, event, ...) -> <object> This element object
|
|
|
|
Unbinds multiple events
|
|
|
|
([event, event, ...]) -> <object> This element object
|
|
|
|
Unbinds multiple events
|
|
|
|
event <string> Event name
|
|
|
|
@*/
|
2011-04-22 22:03:10 +00:00
|
|
|
that.unbindEvent = function() {
|
2011-04-29 22:07:23 +00:00
|
|
|
if (arguments.length == 0) {
|
|
|
|
self.$eventHandler.unbind();
|
2011-04-22 22:03:10 +00:00
|
|
|
} else {
|
2011-04-29 22:07:23 +00:00
|
|
|
Ox.makeArray(arguments).forEach(function(event) {
|
|
|
|
self.$eventHandler.unbind('ox_' + event);
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
return that;
|
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|