| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /**
- * Observable.js
- *
- * Copyright, Moxiecode Systems AB
- * Released under LGPL License.
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
- /**
- * This mixin will add event binding logic to classes.
- *
- * @mixin tinymce.util.Observable
- */
- define("tinymce/util/Observable", [
- "tinymce/util/Tools"
- ], function(Tools) {
- var bindingsName = "__bindings";
- var nativeEvents = Tools.makeMap(
- "focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange" +
- " mouseout mouseenter mouseleave keydown keypress keyup contextmenu dragstart dragend dragover draggesture dragdrop drop drag", ' '
- );
- function returnFalse() {
- return false;
- }
- function returnTrue() {
- return true;
- }
- return {
- /**
- * Fires the specified event by name.
- *
- * @method fire
- * @param {String} name Name of the event to fire.
- * @param {tinymce.Event/Object?} args Event arguments.
- * @param {Boolean?} bubble True/false if the event is to be bubbled.
- * @return {tinymce.Event} Event instance passed in converted into tinymce.Event instance.
- * @example
- * instance.fire('event', {...});
- */
- fire: function(name, args, bubble) {
- var self = this, handlers, i, l, callback, parent;
- name = name.toLowerCase();
- args = args || {};
- args.type = name;
- // Prevent all events except the remove event after the editor has been removed
- if (self.removed && name !== "remove") {
- return;
- }
- // Setup target is there isn't one
- if (!args.target) {
- args.target = self;
- }
- // Add event delegation methods if they are missing
- if (!args.preventDefault) {
- // Add preventDefault method
- args.preventDefault = function() {
- args.isDefaultPrevented = returnTrue;
- };
- // Add stopPropagation
- args.stopPropagation = function() {
- args.isPropagationStopped = returnTrue;
- };
- // Add stopImmediatePropagation
- args.stopImmediatePropagation = function() {
- args.isImmediatePropagationStopped = returnTrue;
- };
- // Add event delegation states
- args.isDefaultPrevented = returnFalse;
- args.isPropagationStopped = returnFalse;
- args.isImmediatePropagationStopped = returnFalse;
- }
- //console.log(name, args);
- if (self[bindingsName]) {
- handlers = self[bindingsName][name];
- if (handlers) {
- for (i = 0, l = handlers.length; i < l; i++) {
- handlers[i] = callback = handlers[i];
- // Stop immediate propagation if needed
- if (args.isImmediatePropagationStopped()) {
- break;
- }
- // If callback returns false then prevent default and stop all propagation
- if (callback.call(self, args) === false) {
- args.preventDefault();
- return args;
- }
- }
- }
- }
- // Bubble event up to parents
- if (bubble !== false && self.parent) {
- parent = self.parent();
- while (parent && !args.isPropagationStopped()) {
- parent.fire(name, args, false);
- parent = parent.parent();
- }
- }
- return args;
- },
- /**
- * Binds an event listener to a specific event by name.
- *
- * @method on
- * @param {String} name Event name or space separated list of events to bind.
- * @param {callback} callback Callback to be executed when the event occurs.
- * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
- * @return {Object} Current class instance.
- * @example
- * instance.on('event', function(e) {
- * // Callback logic
- * });
- */
- on: function(name, callback, prepend) {
- var self = this, bindings, handlers, names, i;
- if (callback === false) {
- callback = function() {
- return false;
- };
- }
- if (callback) {
- names = name.toLowerCase().split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- bindings = self[bindingsName];
- if (!bindings) {
- bindings = self[bindingsName] = {};
- }
- handlers = bindings[name];
- if (!handlers) {
- handlers = bindings[name] = [];
- if (self.bindNative && nativeEvents[name]) {
- self.bindNative(name);
- }
- }
- if (prepend) {
- handlers.unshift(callback);
- } else {
- handlers.push(callback);
- }
- }
- }
- return self;
- },
- /**
- * Unbinds an event listener to a specific event by name.
- *
- * @method off
- * @param {String?} name Name of the event to unbind.
- * @param {callback?} callback Callback to unbind.
- * @return {Object} Current class instance.
- * @example
- * // Unbind specific callback
- * instance.off('event', handler);
- *
- * // Unbind all listeners by name
- * instance.off('event');
- *
- * // Unbind all events
- * instance.off();
- */
- off: function(name, callback) {
- var self = this, i, bindings = self[bindingsName], handlers, bindingName, names, hi;
- if (bindings) {
- if (name) {
- names = name.toLowerCase().split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- handlers = bindings[name];
- // Unbind all handlers
- if (!name) {
- for (bindingName in bindings) {
- bindings[name].length = 0;
- }
- return self;
- }
- if (handlers) {
- // Unbind all by name
- if (!callback) {
- handlers.length = 0;
- } else {
- // Unbind specific ones
- hi = handlers.length;
- while (hi--) {
- if (handlers[hi] === callback) {
- handlers.splice(hi, 1);
- }
- }
- }
- if (!handlers.length && self.unbindNative && nativeEvents[name]) {
- self.unbindNative(name);
- delete bindings[name];
- }
- }
- }
- } else {
- if (self.unbindNative) {
- for (name in bindings) {
- self.unbindNative(name);
- }
- }
- self[bindingsName] = [];
- }
- }
- return self;
- },
- hasEventListeners: function(name) {
- var bindings = this[bindingsName];
- name = name.toLowerCase();
- return !(!bindings || !bindings[name] || bindings[name].length === 0);
- }
- };
- });
|