oxjs/source/Ox.UI/js/Core/Event.js

314 lines
10 KiB
JavaScript
Raw Normal View History

2014-09-23 19:12:31 +00:00
(function() {
var chars = {
comma: ',',
dot: '.',
minus: '-',
quote: '\'',
semicolon: ';',
slash: '/',
space: ' '
},
hasCallback = {},
keyboardEventRegExp = /^key(\.[\w\d.]+)?$/,
keys = '',
keysEventRegExp = new RegExp(
'^[\\w\\d](\\.numpad)?$|^(' + Object.keys(chars).join('|') + ')$'
),
resetTimeout,
triggerTimeout;
function bind(options) {
var args = Ox.slice(arguments, 1),
callbacks = options.callbacks,
that = this;
Ox.forEach(
Ox.isFunction(args[0]) ? {'*': args[0]} : Ox.makeObject(args),
function(originalCallback, event) {
event = event.replace(/^key_/, 'key.');
callbacks[event] = (callbacks[event] || []).concat(
options.once ? function callback() {
unbind.call(
that, {callbacks: callbacks}, event, callback
);
return originalCallback.apply(null, arguments);
}
: originalCallback
);
if (isKeyboardEvent(event)) {
hasCallback[event] = true;
}
}
);
return this;
}
function isKeyboardEvent(event) {
return keyboardEventRegExp.test(event);
2012-06-30 09:24:03 +00:00
}
2011-09-23 10:43:57 +00:00
2014-09-23 19:12:31 +00:00
function isKeysEventKey(key) {
return keysEventRegExp.test(key);
}
function onMessage(e) {
var element, message = {};
try {
message = Ox.extend({data: {}}, JSON.parse(e.data));
} catch (e) {}
if (message.event == 'init') {
if (message.data.oxid) {
// The inner window receives the oxid of the outer iframe element
Ox.oxid = message.data.oxid;
Ox.parent.postMessage('init', {})
} else if (message.target) {
// The outer window receives init from iframe
Ox.elements[message.target].triggerEvent('init');
}
2012-06-29 12:24:06 +00:00
} else {
2014-09-23 19:12:31 +00:00
(message.target ? Ox.elements[message.target] : Ox.parent)
.triggerMessage(message.event, message.data);
}
}
function onKeydown(e) {
var $element = Ox.Focus.focusedElement(),
isInput = Ox.Focus.focusedElementIsInput(),
keyName = Ox.KEYS[e.keyCode],
keyBasename = keyName.split('.')[0],
key = Object.keys(Ox.MODIFIER_KEYS).filter(function(key) {
return e[key] && Ox.MODIFIER_KEYS[key] != keyBasename;
}).map(function(key) {
return Ox.MODIFIER_KEYS[key];
}).concat(keyName).join('_'),
event = 'key.' + key,
2014-09-23 19:12:31 +00:00
triggerEvent = function() {
if ($element) {
$element.triggerEvent.apply($element, arguments);
} else {
Ox.Event.trigger.apply(
Ox.$body, [{}].concat(Ox.slice(arguments))
);
}
};
triggerEvent(event, e);
2014-09-23 19:12:31 +00:00
if (isKeysEventKey(key)) {
// don't register leading spaces or trailing double spaces
if (keyName != 'space' || (
keys != '' && !Ox.endsWith(keys, ' ')
)) {
keys += chars[keyName] || keyBasename;
// clear the trigger timeout only if the key registered
clearTimeout(triggerTimeout);
triggerTimeout = setTimeout(function() {
triggerEvent('keys', Ox.extend(e, {keys: keys}));
}, 250);
2012-06-29 12:24:06 +00:00
}
}
2014-09-23 19:12:31 +00:00
// clear the reset timeout even if the key didn't register
clearTimeout(resetTimeout);
resetTimeout = setTimeout(function() {
keys = '';
}, 1000);
if (hasCallback[event]) {
2014-09-23 19:12:31 +00:00
e.preventDefault();
}
}
function trigger(options) {
var args = Ox.slice(arguments, 1),
callbacks = options.callbacks,
that = this;
Ox.forEach(Ox.makeObject(args), function(data, originalEvent) {
var events = originalEvent.split('.');
['*'].concat(events.map(function(event, index) {
return events.slice(0, index + 1).join('.');
})).forEach(function(event) {
(callbacks[0][event] || [])
.concat(callbacks[1][event] || [])
.forEach(function(callback) {
callback.call(that, data, originalEvent, that);
2012-06-30 09:24:03 +00:00
});
});
2014-09-23 19:12:31 +00:00
});
return this;
}
function unbind(options) {
var args = Ox.slice(arguments, 1),
callbacks = options.callbacks;
2012-06-30 10:15:27 +00:00
if (args.length == 0) {
2014-09-23 19:12:31 +00:00
// unbind all handlers for all events
callbacks = [];
} else {
Ox.forEach(
Ox.isFunction(args[0]) ? {'*': args[0]}
: Ox.makeObject(args),
function(callback, event) {
if (!callback) {
// unbind all handlers for this event
delete callbacks[event];
} else if (callbacks[event]) {
// unbind this handler for this event
callbacks[event] = callbacks[event].filter(
function(eventCallback) {
return eventCallback !== callback;
2012-06-30 10:15:27 +00:00
}
2014-09-23 19:12:31 +00:00
);
if (callbacks[event].length == 0) {
delete callbacks[event];
}
2012-06-30 09:24:03 +00:00
}
2014-09-23 19:12:31 +00:00
if (isKeyboardEvent(event) && !callbacks[event]) {
delete hasCallback[event];
}
}
);
2011-09-23 10:43:57 +00:00
}
2014-09-23 19:12:31 +00:00
return this;
}
Ox.$parent = Ox.parent = (function() {
var self = {messageCallbacks: {}},
that = {oxid: Ox.uid()};
that.bindMessage = function() {
return Ox.Message.bind.apply(
this, [self].concat(Ox.slice(arguments))
);
};
that.bindMessageOnce = function() {
return Ox.Message.bindOnce.apply(
this, [self].concat(Ox.slice(arguments))
);
};
that.postMessage = function() {
2014-09-23 22:00:00 +00:00
if (window !== window.top) {
return Ox.Message.post.apply(this, arguments);
}
2014-09-23 19:12:31 +00:00
};
that.triggerMessage = function() {
return Ox.Message.trigger.apply(
this, [self].concat(Ox.slice(arguments))
);
};
that.unbindMessage = function() {
return Ox.Message.unbind.apply(
this, [self].concat(Ox.slice(arguments))
);
};
return that;
}());
Ox.Event = (function() {
var callbacks = {},
that = {};
that.bind = function() {
var isElement = this !== that;
return bind.apply(this, [{
callbacks: isElement ? arguments[0].eventCallbacks : callbacks
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
that.bindOnce = function() {
var isElement = this !== that;
return bind.apply(this, [{
callbacks: isElement ? arguments[0].eventCallbacks : callbacks,
once: true
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
that.trigger = function(self) {
return trigger.apply(this, [{
callbacks: [callbacks, self.eventCallbacks || {}]
}].concat(Ox.slice(arguments, 1)));
};
that.unbind = function() {
var isElement = this !== that;
return unbind.apply(this, [{
callbacks: isElement ? arguments[0].eventCallbacks : callbacks
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
2011-09-23 10:43:57 +00:00
return that;
2014-09-23 19:12:31 +00:00
}());
Ox.Message = (function() {
var callbacks = {},
that = {};
that.bind = function() {
var isElement = this !== that;
return bind.apply(this, [{
callbacks: isElement ? arguments[0].messageCallbacks
: callbacks
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
that.bindOnce = function() {
var isElement = this !== that;
return bind.apply(this, [{
callbacks: isElement ? arguments[0].messageCallbacks
: callbacks,
once: true
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
that.post = function() {
var args = arguments,
isParent = this == Ox.parent,
target = isParent ? window.parent : this[0].contentWindow,
that = this;
if (isParent && !Ox.oxid) {
// posting to parent, but not yet initialized
setTimeout(function() {
that.post.apply(Ox.parent, args);
2014-09-23 22:00:00 +00:00
}, 250);
} else {
Ox.forEach(
Ox.makeObject(Ox.slice(args)),
function(data, event) {
target.postMessage(JSON.stringify({
data: data,
event: event,
target: isParent ? Ox.oxid : null
}), '*');
}
);
2014-09-23 19:12:31 +00:00
}
};
that.trigger = function(self) {
return trigger.apply(this, [{
callbacks: [callbacks, self.messageCallbacks]
}].concat(Ox.slice(arguments, 1)));
};
that.unbind = function() {
var isElement = this !== that;
return unbind.apply(this, [{
callbacks: isElement ? arguments[0].messageCallbacks
: callbacks
}].concat(Ox.slice(arguments, isElement ? 1 : 0)));
};
return that;
}());
document.addEventListener('keydown', onKeydown);
window.addEventListener('message', onMessage);
2011-09-23 10:43:57 +00:00
2014-09-23 19:12:31 +00:00
}());