diff options
Diffstat (limited to 'src/js/util/mxEvent.js')
-rw-r--r-- | src/js/util/mxEvent.js | 1175 |
1 files changed, 1175 insertions, 0 deletions
diff --git a/src/js/util/mxEvent.js b/src/js/util/mxEvent.js new file mode 100644 index 0000000..f831631 --- /dev/null +++ b/src/js/util/mxEvent.js @@ -0,0 +1,1175 @@ +/** + * $Id: mxEvent.js,v 1.76 2012-12-07 07:39:03 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxEvent = +{ + + /** + * Class: mxEvent + * + * Cross-browser DOM event support. For internal event handling, + * <mxEventSource> and the graph event dispatch loop in <mxGraph> are used. + * + * Memory Leaks: + * + * Use this class for adding and removing listeners to/from DOM nodes. The + * <removeAllListeners> function is provided to remove all listeners that + * have been added using <addListener>. The function should be invoked when + * the last reference is removed in the JavaScript code, typically when the + * referenced DOM node is removed from the DOM, and helps to reduce memory + * leaks in IE6. + * + * Variable: objects + * + * Contains all objects where any listener was added using <addListener>. + * This is used to reduce memory leaks in IE, see <mxClient.dispose>. + */ + objects: [], + + /** + * Function: addListener + * + * Binds the function to the specified event on the given element. Use + * <mxUtils.bind> in order to bind the "this" keyword inside the function + * to a given execution scope. + */ + addListener: function() + { + var updateListenerList = function(element, eventName, funct) + { + if (element.mxListenerList == null) + { + element.mxListenerList = []; + mxEvent.objects.push(element); + } + + var entry = {name: eventName, f: funct}; + element.mxListenerList.push(entry); + }; + + if (window.addEventListener) + { + return function(element, eventName, funct) + { + element.addEventListener(eventName, funct, false); + updateListenerList(element, eventName, funct); + }; + } + else + { + return function(element, eventName, funct) + { + element.attachEvent('on' + eventName, funct); + updateListenerList(element, eventName, funct); + }; + } + }(), + + /** + * Function: removeListener + * + * Removes the specified listener from the given element. + */ + removeListener: function() + { + var updateListener = function(element, eventName, funct) + { + if (element.mxListenerList != null) + { + var listenerCount = element.mxListenerList.length; + + for (var i=0; i<listenerCount; i++) + { + var entry = element.mxListenerList[i]; + + if (entry.f == funct) + { + element.mxListenerList.splice(i, 1); + break; + } + } + + if (element.mxListenerList.length == 0) + { + element.mxListenerList = null; + } + } + }; + + if (window.removeEventListener) + { + return function(element, eventName, funct) + { + element.removeEventListener(eventName, funct, false); + updateListener(element, eventName, funct); + }; + } + else + { + return function(element, eventName, funct) + { + element.detachEvent('on' + eventName, funct); + updateListener(element, eventName, funct); + }; + } + }(), + + /** + * Function: removeAllListeners + * + * Removes all listeners from the given element. + */ + removeAllListeners: function(element) + { + var list = element.mxListenerList; + + if (list != null) + { + while (list.length > 0) + { + var entry = list[0]; + mxEvent.removeListener(element, entry.name, entry.f); + } + } + }, + + /** + * Function: redirectMouseEvents + * + * Redirects the mouse events from the given DOM node to the graph dispatch + * loop using the event and given state as event arguments. State can + * either be an instance of <mxCellState> or a function that returns an + * <mxCellState>. The down, move, up and dblClick arguments are optional + * functions that take the trigger event as arguments and replace the + * default behaviour. + */ + redirectMouseEvents: function(node, graph, state, down, move, up, dblClick) + { + var getState = function(evt) + { + return (typeof(state) == 'function') ? state(evt) : state; + }; + + var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown'; + var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove'; + var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup'; + + mxEvent.addListener(node, md, function (evt) + { + if (down != null) + { + down(evt); + } + else if (!mxEvent.isConsumed(evt)) + { + graph.fireMouseEvent(mxEvent.MOUSE_DOWN, + new mxMouseEvent(evt, getState(evt))); + } + }); + + mxEvent.addListener(node, mm, function (evt) + { + if (move != null) + { + move(evt); + } + else if (!mxEvent.isConsumed(evt)) + { + graph.fireMouseEvent(mxEvent.MOUSE_MOVE, + new mxMouseEvent(evt, getState(evt))); + } + }); + + mxEvent.addListener(node, mu, function (evt) + { + if (up != null) + { + up(evt); + } + else if (!mxEvent.isConsumed(evt)) + { + graph.fireMouseEvent(mxEvent.MOUSE_UP, + new mxMouseEvent(evt, getState(evt))); + } + }); + + mxEvent.addListener(node, 'dblclick', function (evt) + { + if (dblClick != null) + { + dblClick(evt); + } + else if (!mxEvent.isConsumed(evt)) + { + var tmp = getState(evt); + graph.dblClick(evt, (tmp != null) ? tmp.cell : null); + } + }); + }, + + /** + * Function: release + * + * Removes the known listeners from the given DOM node and its descendants. + * + * Parameters: + * + * element - DOM node to remove the listeners from. + */ + release: function(element) + { + if (element != null) + { + mxEvent.removeAllListeners(element); + + var children = element.childNodes; + + if (children != null) + { + var childCount = children.length; + + for (var i = 0; i < childCount; i += 1) + { + mxEvent.release(children[i]); + } + } + } + }, + + /** + * Function: addMouseWheelListener + * + * Installs the given function as a handler for mouse wheel events. The + * function has two arguments: the mouse event and a boolean that specifies + * if the wheel was moved up or down. + * + * This has been tested with IE 6 and 7, Firefox (all versions), Opera and + * Safari. It does currently not work on Safari for Mac. + * + * Example: + * + * (code) + * mxEvent.addMouseWheelListener(function (evt, up) + * { + * mxLog.show(); + * mxLog.debug('mouseWheel: up='+up); + * }); + *(end) + * + * Parameters: + * + * funct - Handler function that takes the event argument and a boolean up + * argument for the mousewheel direction. + */ + addMouseWheelListener: function(funct) + { + if (funct != null) + { + var wheelHandler = function(evt) + { + // IE does not give an event object but the + // global event object is the mousewheel event + // at this point in time. + if (evt == null) + { + evt = window.event; + } + + var delta = 0; + + if (mxClient.IS_NS && !mxClient.IS_SF && !mxClient.IS_GC) + { + delta = -evt.detail/2; + } + else + { + delta = evt.wheelDelta/120; + } + + // Handles the event using the given function + if (delta != 0) + { + funct(evt, delta > 0); + } + }; + + // Webkit has NS event API, but IE event name and details + if (mxClient.IS_NS) + { + var eventName = (mxClient.IS_SF || mxClient.IS_GC) ? + 'mousewheel' : 'DOMMouseScroll'; + mxEvent.addListener(window, eventName, wheelHandler); + } + else + { + // TODO: Does not work with Safari and Chrome but it should be + // working as tested in etc/markup/wheel.html + mxEvent.addListener(document, 'mousewheel', wheelHandler); + } + } + }, + + /** + * Function: disableContextMenu + * + * Disables the context menu for the given element. + */ + disableContextMenu: function() + { + if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) + { + return function(element) + { + mxEvent.addListener(element, 'contextmenu', function() + { + return false; + }); + }; + } + else + { + return function(element) + { + element.setAttribute('oncontextmenu', 'return false;'); + }; + } + }(), + + /** + * Function: getSource + * + * Returns the event's target or srcElement depending on the browser. + */ + getSource: function(evt) + { + return (evt.srcElement != null) ? evt.srcElement : evt.target; + }, + + /** + * Function: isConsumed + * + * Returns true if the event has been consumed using <consume>. + */ + isConsumed: function(evt) + { + return evt.isConsumed != null && evt.isConsumed; + }, + + /** + * Function: isLeftMouseButton + * + * Returns true if the left mouse button is pressed for the given event. + * To check if a button is pressed during a mouseMove you should use the + * <mxGraph.isMouseDown> property. + */ + isLeftMouseButton: function(evt) + { + return evt.button == ((mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) ? 1 : 0); + }, + + /** + * Function: isRightMouseButton + * + * Returns true if the right mouse button was pressed. Note that this + * button might not be available on some systems. For handling a popup + * trigger <isPopupTrigger> should be used. + */ + isRightMouseButton: function(evt) + { + return evt.button == 2; + }, + + /** + * Function: isPopupTrigger + * + * Returns true if the event is a popup trigger. This implementation + * returns true if the right mouse button or shift was pressed. + */ + isPopupTrigger: function(evt) + { + return mxEvent.isRightMouseButton(evt) || + (mxEvent.isShiftDown(evt) && + !mxEvent.isControlDown(evt)); + }, + + /** + * Function: isShiftDown + * + * Returns true if the shift key is pressed for the given event. + */ + isShiftDown: function(evt) + { + return (evt != null) ? evt.shiftKey : false; + }, + + /** + * Function: isAltDown + * + * Returns true if the alt key is pressed for the given event. + */ + isAltDown: function(evt) + { + return (evt != null) ? evt.altKey : false; + }, + + /** + * Function: isControlDown + * + * Returns true if the control key is pressed for the given event. + */ + isControlDown: function(evt) + { + return (evt != null) ? evt.ctrlKey : false; + }, + + /** + * Function: isMetaDown + * + * Returns true if the meta key is pressed for the given event. + */ + isMetaDown: function(evt) + { + return (evt != null) ? evt.metaKey : false; + }, + + /** + * Function: getMainEvent + * + * Returns the touch or mouse event that contains the mouse coordinates. + */ + getMainEvent: function(e) + { + if ((e.type == 'touchstart' || e.type == 'touchmove') && + e.touches != null && e.touches[0] != null) + { + e = e.touches[0]; + } + else if (e.type == 'touchend' && e.changedTouches != null && + e.changedTouches[0] != null) + { + e = e.changedTouches[0]; + } + + return e; + }, + + /** + * Function: getClientX + * + * Returns true if the meta key is pressed for the given event. + */ + getClientX: function(e) + { + return mxEvent.getMainEvent(e).clientX; + }, + + /** + * Function: getClientY + * + * Returns true if the meta key is pressed for the given event. + */ + getClientY: function(e) + { + return mxEvent.getMainEvent(e).clientY; + }, + + /** + * Function: consume + * + * Consumes the given event. + * + * Parameters: + * + * evt - Native event to be consumed. + * preventDefault - Optional boolean to prevent the default for the event. + * Default is true. + * stopPropagation - Option boolean to stop event propagation. Default is + * true. + */ + consume: function(evt, preventDefault, stopPropagation) + { + preventDefault = (preventDefault != null) ? preventDefault : true; + stopPropagation = (stopPropagation != null) ? stopPropagation : true; + + if (preventDefault) + { + if (evt.preventDefault) + { + if (stopPropagation) + { + evt.stopPropagation(); + } + + evt.preventDefault(); + } + else if (stopPropagation) + { + evt.cancelBubble = true; + } + } + + // Opera + evt.isConsumed = true; + + // Other browsers + evt.returnValue = false; + }, + + // + // Special handles in mouse events + // + + /** + * Variable: LABEL_HANDLE + * + * Index for the label handle in an mxMouseEvent. This should be a negative + * value that does not interfere with any possible handle indices. Default + * is -1. + */ + LABEL_HANDLE: -1, + + /** + * Variable: ROTATION_HANDLE + * + * Index for the rotation handle in an mxMouseEvent. This should be a + * negative value that does not interfere with any possible handle indices. + * Default is -2. + */ + ROTATION_HANDLE: -2, + + // + // Event names + // + + /** + * Variable: MOUSE_DOWN + * + * Specifies the event name for mouseDown. + */ + MOUSE_DOWN: 'mouseDown', + + /** + * Variable: MOUSE_MOVE + * + * Specifies the event name for mouseMove. + */ + MOUSE_MOVE: 'mouseMove', + + /** + * Variable: MOUSE_UP + * + * Specifies the event name for mouseUp. + */ + MOUSE_UP: 'mouseUp', + + /** + * Variable: ACTIVATE + * + * Specifies the event name for activate. + */ + ACTIVATE: 'activate', + + /** + * Variable: RESIZE_START + * + * Specifies the event name for resizeStart. + */ + RESIZE_START: 'resizeStart', + + /** + * Variable: RESIZE + * + * Specifies the event name for resize. + */ + RESIZE: 'resize', + + /** + * Variable: RESIZE_END + * + * Specifies the event name for resizeEnd. + */ + RESIZE_END: 'resizeEnd', + + /** + * Variable: MOVE_START + * + * Specifies the event name for moveStart. + */ + MOVE_START: 'moveStart', + + /** + * Variable: MOVE + * + * Specifies the event name for move. + */ + MOVE: 'move', + + /** + * Variable: MOVE_END + * + * Specifies the event name for moveEnd. + */ + MOVE_END: 'moveEnd', + + /** + * Variable: PAN_START + * + * Specifies the event name for panStart. + */ + PAN_START: 'panStart', + + /** + * Variable: PAN + * + * Specifies the event name for pan. + */ + PAN: 'pan', + + /** + * Variable: PAN_END + * + * Specifies the event name for panEnd. + */ + PAN_END: 'panEnd', + + /** + * Variable: MINIMIZE + * + * Specifies the event name for minimize. + */ + MINIMIZE: 'minimize', + + /** + * Variable: NORMALIZE + * + * Specifies the event name for normalize. + */ + NORMALIZE: 'normalize', + + /** + * Variable: MAXIMIZE + * + * Specifies the event name for maximize. + */ + MAXIMIZE: 'maximize', + + /** + * Variable: HIDE + * + * Specifies the event name for hide. + */ + HIDE: 'hide', + + /** + * Variable: SHOW + * + * Specifies the event name for show. + */ + SHOW: 'show', + + /** + * Variable: CLOSE + * + * Specifies the event name for close. + */ + CLOSE: 'close', + + /** + * Variable: DESTROY + * + * Specifies the event name for destroy. + */ + DESTROY: 'destroy', + + /** + * Variable: REFRESH + * + * Specifies the event name for refresh. + */ + REFRESH: 'refresh', + + /** + * Variable: SIZE + * + * Specifies the event name for size. + */ + SIZE: 'size', + + /** + * Variable: SELECT + * + * Specifies the event name for select. + */ + SELECT: 'select', + + /** + * Variable: FIRED + * + * Specifies the event name for fired. + */ + FIRED: 'fired', + + /** + * Variable: GET + * + * Specifies the event name for get. + */ + GET: 'get', + + /** + * Variable: RECEIVE + * + * Specifies the event name for receive. + */ + RECEIVE: 'receive', + + /** + * Variable: CONNECT + * + * Specifies the event name for connect. + */ + CONNECT: 'connect', + + /** + * Variable: DISCONNECT + * + * Specifies the event name for disconnect. + */ + DISCONNECT: 'disconnect', + + /** + * Variable: SUSPEND + * + * Specifies the event name for suspend. + */ + SUSPEND: 'suspend', + + /** + * Variable: RESUME + * + * Specifies the event name for suspend. + */ + RESUME: 'resume', + + /** + * Variable: MARK + * + * Specifies the event name for mark. + */ + MARK: 'mark', + + /** + * Variable: SESSION + * + * Specifies the event name for session. + */ + SESSION: 'session', + + /** + * Variable: ROOT + * + * Specifies the event name for root. + */ + ROOT: 'root', + + /** + * Variable: POST + * + * Specifies the event name for post. + */ + POST: 'post', + + /** + * Variable: OPEN + * + * Specifies the event name for open. + */ + OPEN: 'open', + + /** + * Variable: SAVE + * + * Specifies the event name for open. + */ + SAVE: 'save', + + /** + * Variable: BEFORE_ADD_VERTEX + * + * Specifies the event name for beforeAddVertex. + */ + BEFORE_ADD_VERTEX: 'beforeAddVertex', + + /** + * Variable: ADD_VERTEX + * + * Specifies the event name for addVertex. + */ + ADD_VERTEX: 'addVertex', + + /** + * Variable: AFTER_ADD_VERTEX + * + * Specifies the event name for afterAddVertex. + */ + AFTER_ADD_VERTEX: 'afterAddVertex', + + /** + * Variable: DONE + * + * Specifies the event name for done. + */ + DONE: 'done', + + /** + * Variable: EXECUTE + * + * Specifies the event name for execute. + */ + EXECUTE: 'execute', + + /** + * Variable: BEGIN_UPDATE + * + * Specifies the event name for beginUpdate. + */ + BEGIN_UPDATE: 'beginUpdate', + + /** + * Variable: END_UPDATE + * + * Specifies the event name for endUpdate. + */ + END_UPDATE: 'endUpdate', + + /** + * Variable: BEFORE_UNDO + * + * Specifies the event name for beforeUndo. + */ + BEFORE_UNDO: 'beforeUndo', + + /** + * Variable: UNDO + * + * Specifies the event name for undo. + */ + UNDO: 'undo', + + /** + * Variable: REDO + * + * Specifies the event name for redo. + */ + REDO: 'redo', + + /** + * Variable: CHANGE + * + * Specifies the event name for change. + */ + CHANGE: 'change', + + /** + * Variable: NOTIFY + * + * Specifies the event name for notify. + */ + NOTIFY: 'notify', + + /** + * Variable: LAYOUT_CELLS + * + * Specifies the event name for layoutCells. + */ + LAYOUT_CELLS: 'layoutCells', + + /** + * Variable: CLICK + * + * Specifies the event name for click. + */ + CLICK: 'click', + + /** + * Variable: SCALE + * + * Specifies the event name for scale. + */ + SCALE: 'scale', + + /** + * Variable: TRANSLATE + * + * Specifies the event name for translate. + */ + TRANSLATE: 'translate', + + /** + * Variable: SCALE_AND_TRANSLATE + * + * Specifies the event name for scaleAndTranslate. + */ + SCALE_AND_TRANSLATE: 'scaleAndTranslate', + + /** + * Variable: UP + * + * Specifies the event name for up. + */ + UP: 'up', + + /** + * Variable: DOWN + * + * Specifies the event name for down. + */ + DOWN: 'down', + + /** + * Variable: ADD + * + * Specifies the event name for add. + */ + ADD: 'add', + + /** + * Variable: REMOVE + * + * Specifies the event name for remove. + */ + REMOVE: 'remove', + + /** + * Variable: CLEAR + * + * Specifies the event name for clear. + */ + CLEAR: 'clear', + + /** + * Variable: ADD_CELLS + * + * Specifies the event name for addCells. + */ + ADD_CELLS: 'addCells', + + /** + * Variable: CELLS_ADDED + * + * Specifies the event name for cellsAdded. + */ + CELLS_ADDED: 'cellsAdded', + + /** + * Variable: MOVE_CELLS + * + * Specifies the event name for moveCells. + */ + MOVE_CELLS: 'moveCells', + + /** + * Variable: CELLS_MOVED + * + * Specifies the event name for cellsMoved. + */ + CELLS_MOVED: 'cellsMoved', + + /** + * Variable: RESIZE_CELLS + * + * Specifies the event name for resizeCells. + */ + RESIZE_CELLS: 'resizeCells', + + /** + * Variable: CELLS_RESIZED + * + * Specifies the event name for cellsResized. + */ + CELLS_RESIZED: 'cellsResized', + + /** + * Variable: TOGGLE_CELLS + * + * Specifies the event name for toggleCells. + */ + TOGGLE_CELLS: 'toggleCells', + + /** + * Variable: CELLS_TOGGLED + * + * Specifies the event name for cellsToggled. + */ + CELLS_TOGGLED: 'cellsToggled', + + /** + * Variable: ORDER_CELLS + * + * Specifies the event name for orderCells. + */ + ORDER_CELLS: 'orderCells', + + /** + * Variable: CELLS_ORDERED + * + * Specifies the event name for cellsOrdered. + */ + CELLS_ORDERED: 'cellsOrdered', + + /** + * Variable: REMOVE_CELLS + * + * Specifies the event name for removeCells. + */ + REMOVE_CELLS: 'removeCells', + + /** + * Variable: CELLS_REMOVED + * + * Specifies the event name for cellsRemoved. + */ + CELLS_REMOVED: 'cellsRemoved', + + /** + * Variable: GROUP_CELLS + * + * Specifies the event name for groupCells. + */ + GROUP_CELLS: 'groupCells', + + /** + * Variable: UNGROUP_CELLS + * + * Specifies the event name for ungroupCells. + */ + UNGROUP_CELLS: 'ungroupCells', + + /** + * Variable: REMOVE_CELLS_FROM_PARENT + * + * Specifies the event name for removeCellsFromParent. + */ + REMOVE_CELLS_FROM_PARENT: 'removeCellsFromParent', + + /** + * Variable: FOLD_CELLS + * + * Specifies the event name for foldCells. + */ + FOLD_CELLS: 'foldCells', + + /** + * Variable: CELLS_FOLDED + * + * Specifies the event name for cellsFolded. + */ + CELLS_FOLDED: 'cellsFolded', + + /** + * Variable: ALIGN_CELLS + * + * Specifies the event name for alignCells. + */ + ALIGN_CELLS: 'alignCells', + + /** + * Variable: LABEL_CHANGED + * + * Specifies the event name for labelChanged. + */ + LABEL_CHANGED: 'labelChanged', + + /** + * Variable: CONNECT_CELL + * + * Specifies the event name for connectCell. + */ + CONNECT_CELL: 'connectCell', + + /** + * Variable: CELL_CONNECTED + * + * Specifies the event name for cellConnected. + */ + CELL_CONNECTED: 'cellConnected', + + /** + * Variable: SPLIT_EDGE + * + * Specifies the event name for splitEdge. + */ + SPLIT_EDGE: 'splitEdge', + + /** + * Variable: FLIP_EDGE + * + * Specifies the event name for flipEdge. + */ + FLIP_EDGE: 'flipEdge', + + /** + * Variable: START_EDITING + * + * Specifies the event name for startEditing. + */ + START_EDITING: 'startEditing', + + /** + * Variable: ADD_OVERLAY + * + * Specifies the event name for addOverlay. + */ + ADD_OVERLAY: 'addOverlay', + + /** + * Variable: REMOVE_OVERLAY + * + * Specifies the event name for removeOverlay. + */ + REMOVE_OVERLAY: 'removeOverlay', + + /** + * Variable: UPDATE_CELL_SIZE + * + * Specifies the event name for updateCellSize. + */ + UPDATE_CELL_SIZE: 'updateCellSize', + + /** + * Variable: ESCAPE + * + * Specifies the event name for escape. + */ + ESCAPE: 'escape', + + /** + * Variable: CLICK + * + * Specifies the event name for click. + */ + CLICK: 'click', + + /** + * Variable: DOUBLE_CLICK + * + * Specifies the event name for doubleClick. + */ + DOUBLE_CLICK: 'doubleClick', + + /** + * Variable: START + * + * Specifies the event name for start. + */ + START: 'start', + + /** + * Variable: RESET + * + * Specifies the event name for reset. + */ + RESET: 'reset' + +}; |