diff options
author | Adhitya Kamakshidasan | 2016-06-28 16:10:23 +0530 |
---|---|---|
committer | GitHub | 2016-06-28 16:10:23 +0530 |
commit | 138109bd9af1904cffb2da7677a97042b91658d3 (patch) | |
tree | c6c080cfd78593dbe5cb4d6a576f2b7474007fc2 | |
parent | a7ad30ee3ddd46886820419a58ec05759a842517 (diff) | |
parent | a45361eb58f86535805185d16b91ae05339e7771 (diff) | |
download | xcos-on-web-138109bd9af1904cffb2da7677a97042b91658d3.tar.gz xcos-on-web-138109bd9af1904cffb2da7677a97042b91658d3.tar.bz2 xcos-on-web-138109bd9af1904cffb2da7677a97042b91658d3.zip |
Merge pull request #85 from jiteshjha/repository-refactoring
Repository refactoring
-rw-r--r-- | dependencies.js | 2 | ||||
-rw-r--r-- | editor/mxDefaultKeyHandler.js | 126 | ||||
-rw-r--r-- | editor/mxDefaultPopupMenu.js | 300 | ||||
-rw-r--r-- | editor/mxDefaultToolbar.js | 567 | ||||
-rw-r--r-- | editor/mxEditor.js | 3220 | ||||
-rw-r--r-- | handler/mxKeyHandler.js | 402 | ||||
-rw-r--r-- | index.html | 7 | ||||
-rw-r--r-- | json2.js | 519 | ||||
-rw-r--r-- | test.html | 2226 |
9 files changed, 3 insertions, 7366 deletions
diff --git a/dependencies.js b/dependencies.js index 11f6d97..17c2184 100644 --- a/dependencies.js +++ b/dependencies.js @@ -475,4 +475,4 @@ function inverse() { str += arg + "]]"; var array = JSON.parse(str); return array; -}
\ No newline at end of file +} diff --git a/editor/mxDefaultKeyHandler.js b/editor/mxDefaultKeyHandler.js deleted file mode 100644 index 3814e5e..0000000 --- a/editor/mxDefaultKeyHandler.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * $Id: mxDefaultKeyHandler.js,v 1.26 2010-01-02 09:45:15 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxDefaultKeyHandler - * - * Binds keycodes to actionnames in an editor. This aggregates an internal - * <handler> and extends the implementation of <mxKeyHandler.escape> to not - * only cancel the editing, but also hide the properties dialog and fire an - * <mxEditor.escape> event via <editor>. An instance of this class is created - * by <mxEditor> and stored in <mxEditor.keyHandler>. - * - * Example: - * - * Bind the delete key to the delete action in an existing editor. - * - * (code) - * var keyHandler = new mxDefaultKeyHandler(editor); - * keyHandler.bindAction(46, 'delete'); - * (end) - * - * Codec: - * - * This class uses the <mxDefaultKeyHandlerCodec> to read configuration - * data into an existing instance. See <mxDefaultKeyHandlerCodec> for a - * description of the configuration format. - * - * Keycodes: - * - * See <mxKeyHandler>. - * - * An <mxEvent.ESCAPE> event is fired via the editor if the escape key is - * pressed. - * - * Constructor: mxDefaultKeyHandler - * - * Constructs a new default key handler for the <mxEditor.graph> in the - * given <mxEditor>. (The editor may be null if a prototypical instance for - * a <mxDefaultKeyHandlerCodec> is created.) - * - * Parameters: - * - * editor - Reference to the enclosing <mxEditor>. - */ -function mxDefaultKeyHandler(editor) -{ - if (editor != null) - { - this.editor = editor; - this.handler = new mxKeyHandler(editor.graph); - - // Extends the escape function of the internal key - // handle to hide the properties dialog and fire - // the escape event via the editor instance - var old = this.handler.escape; - - this.handler.escape = function(evt) - { - old.apply(this, arguments); - editor.hideProperties(); - editor.fireEvent(new mxEventObject(mxEvent.ESCAPE, 'event', evt)); - }; - } -}; - -/** - * Variable: editor - * - * Reference to the enclosing <mxEditor>. - */ -mxDefaultKeyHandler.prototype.editor = null; - -/** - * Variable: handler - * - * Holds the <mxKeyHandler> for key event handling. - */ -mxDefaultKeyHandler.prototype.handler = null; - -/** - * Function: bindAction - * - * Binds the specified keycode to the given action in <editor>. The - * optional control flag specifies if the control key must be pressed - * to trigger the action. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * action - Name of the action to execute in <editor>. - * control - Optional boolean that specifies if control must be pressed. - * Default is false. - */ -mxDefaultKeyHandler.prototype.bindAction = function (code, action, control) -{ - var keyHandler = mxUtils.bind(this, function() - { - this.editor.execute(action); - }); - - // Binds the function to control-down keycode - if (control) - { - this.handler.bindControlKey(code, keyHandler); - } - - // Binds the function to the normal keycode - else - { - this.handler.bindKey(code, keyHandler); - } -}; - -/** - * Function: destroy - * - * Destroys the <handler> associated with this object. This does normally - * not need to be called, the <handler> is destroyed automatically when the - * window unloads (in IE) by <mxEditor>. - */ -mxDefaultKeyHandler.prototype.destroy = function () -{ - this.handler.destroy(); - this.handler = null; -}; diff --git a/editor/mxDefaultPopupMenu.js b/editor/mxDefaultPopupMenu.js deleted file mode 100644 index 01c65b5..0000000 --- a/editor/mxDefaultPopupMenu.js +++ /dev/null @@ -1,300 +0,0 @@ -/** - * $Id: mxDefaultPopupMenu.js,v 1.29 2012-07-03 06:30:25 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxDefaultPopupMenu - * - * Creates popupmenus for mouse events. This object holds an XML node - * which is a description of the popup menu to be created. In - * <createMenu>, the configuration is applied to the context and - * the resulting menu items are added to the menu dynamically. See - * <createMenu> for a description of the configuration format. - * - * This class does not create the DOM nodes required for the popup menu, it - * only parses an XML description to invoke the respective methods on an - * <mxPopupMenu> each time the menu is displayed. - * - * Codec: - * - * This class uses the <mxDefaultPopupMenuCodec> to read configuration - * data into an existing instance, however, the actual parsing is done - * by this class during program execution, so the format is described - * below. - * - * Constructor: mxDefaultPopupMenu - * - * Constructs a new popupmenu-factory based on given configuration. - * - * Paramaters: - * - * config - XML node that contains the configuration data. - */ -function mxDefaultPopupMenu(config) -{ - this.config = config; -}; - -/** - * Variable: imageBasePath - * - * Base path for all icon attributes in the config. Default is null. - */ -mxDefaultPopupMenu.prototype.imageBasePath = null; - -/** - * Variable: config - * - * XML node used as the description of new menu items. This node is - * used in <createMenu> to dynamically create the menu items if their - * respective conditions evaluate to true for the given arguments. - */ -mxDefaultPopupMenu.prototype.config = null; - -/** - * Function: createMenu - * - * This function is called from <mxEditor> to add items to the - * given menu based on <config>. The config is a sequence of - * the following nodes and attributes. - * - * Child Nodes: - * - * add - Adds a new menu item. See below for attributes. - * separator - Adds a separator. No attributes. - * condition - Adds a custom condition. Name attribute. - * - * The add-node may have a child node that defines a function to be invoked - * before the action is executed (or instead of an action to be executed). - * - * Attributes: - * - * as - Resource key for the label (needs entry in property file). - * action - Name of the action to execute in enclosing editor. - * icon - Optional icon (relative/absolute URL). - * iconCls - Optional CSS class for the icon. - * if - Optional name of condition that must be true(see below). - * name - Name of custom condition. Only for condition nodes. - * - * Conditions: - * - * nocell - No cell under the mouse. - * ncells - More than one cell selected. - * notRoot - Drilling position is other than home. - * cell - Cell under the mouse. - * notEmpty - Exactly one cell with children under mouse. - * expandable - Exactly one expandable cell under mouse. - * collapsable - Exactly one collapsable cell under mouse. - * validRoot - Exactly one cell which is a possible root under mouse. - * swimlane - Exactly one cell which is a swimlane under mouse. - * - * Example: - * - * To add a new item for a given action to the popupmenu: - * - * (code) - * <mxDefaultPopupMenu as="popupHandler"> - * <add as="delete" action="delete" icon="images/delete.gif" if="cell"/> - * </mxDefaultPopupMenu> - * (end) - * - * To add a new item for a custom function: - * - * (code) - * <mxDefaultPopupMenu as="popupHandler"> - * <add as="action1"><![CDATA[ - * function (editor, cell, evt) - * { - * editor.execute('action1', cell, 'myArg'); - * } - * ]]></add> - * </mxDefaultPopupMenu> - * (end) - * - * The above example invokes action1 with an additional third argument via - * the editor instance. The third argument is passed to the function that - * defines action1. If the add-node has no action-attribute, then only the - * function defined in the text content is executed, otherwise first the - * function and then the action defined in the action-attribute is - * executed. The function in the text content has 3 arguments, namely the - * <mxEditor> instance, the <mxCell> instance under the mouse, and the - * native mouse event. - * - * Custom Conditions: - * - * To add a new condition for popupmenu items: - * - * (code) - * <condition name="condition1"><![CDATA[ - * function (editor, cell, evt) - * { - * return cell != null; - * } - * ]]></condition> - * (end) - * - * The new condition can then be used in any item as follows: - * - * (code) - * <add as="action1" action="action1" icon="action1.gif" if="condition1"/> - * (end) - * - * The order in which the items and conditions appear is not significant as - * all connditions are evaluated before any items are created. - * - * Parameters: - * - * editor - Enclosing <mxEditor> instance. - * menu - <mxPopupMenu> that is used for adding items and separators. - * cell - Optional <mxCell> which is under the mousepointer. - * evt - Optional mouse event which triggered the menu. - */ -mxDefaultPopupMenu.prototype.createMenu = function(editor, menu, cell, evt) -{ - if (this.config != null) - { - var conditions = this.createConditions(editor, cell, evt); - var item = this.config.firstChild; - - this.addItems(editor, menu, cell, evt, conditions, item, null); - } -}; - -/** - * Function: addItems - * - * Recursively adds the given items and all of its children into the given menu. - * - * Parameters: - * - * editor - Enclosing <mxEditor> instance. - * menu - <mxPopupMenu> that is used for adding items and separators. - * cell - Optional <mxCell> which is under the mousepointer. - * evt - Optional mouse event which triggered the menu. - * conditions - Array of names boolean conditions. - * item - XML node that represents the current menu item. - * parent - DOM node that represents the parent menu item. - */ -mxDefaultPopupMenu.prototype.addItems = function(editor, menu, cell, evt, conditions, item, parent) -{ - var addSeparator = false; - - while (item != null) - { - if (item.nodeName == 'add') - { - var condition = item.getAttribute('if'); - - if (condition == null || conditions[condition]) - { - var as = item.getAttribute('as'); - as = mxResources.get(as) || as; - var funct = mxUtils.eval(mxUtils.getTextContent(item)); - var action = item.getAttribute('action'); - var icon = item.getAttribute('icon'); - var iconCls = item.getAttribute('iconCls'); - - if (addSeparator) - { - menu.addSeparator(parent); - addSeparator = false; - } - - if (icon != null && this.imageBasePath) - { - icon = this.imageBasePath + icon; - } - - var row = this.addAction(menu, editor, as, icon, funct, action, cell, parent, iconCls); - this.addItems(editor, menu, cell, evt, conditions, item.firstChild, row); - } - } - else if (item.nodeName == 'separator') - { - addSeparator = true; - } - - item = item.nextSibling; - } -}; - -/** - * Function: addAction - * - * Helper method to bind an action to a new menu item. - * - * Parameters: - * - * menu - <mxPopupMenu> that is used for adding items and separators. - * editor - Enclosing <mxEditor> instance. - * lab - String that represents the label of the menu item. - * icon - Optional URL that represents the icon of the menu item. - * action - Optional name of the action to execute in the given editor. - * funct - Optional function to execute before the optional action. The - * function takes an <mxEditor>, the <mxCell> under the mouse and the - * mouse event that triggered the call. - * cell - Optional <mxCell> to use as an argument for the action. - * parent - DOM node that represents the parent menu item. - * iconCls - Optional CSS class for the menu icon. - */ -mxDefaultPopupMenu.prototype.addAction = function(menu, editor, lab, icon, funct, action, cell, parent, iconCls) -{ - var clickHandler = function(evt) - { - if (typeof(funct) == 'function') - { - funct.call(editor, editor, cell, evt); - } - - if (action != null) - { - editor.execute(action, cell, evt); - } - }; - - return menu.addItem(lab, icon, clickHandler, parent, iconCls); -}; - -/** - * Function: createConditions - * - * Evaluates the default conditions for the given context. - */ -mxDefaultPopupMenu.prototype.createConditions = function(editor, cell, evt) -{ - // Creates array with conditions - var model = editor.graph.getModel(); - var childCount = model.getChildCount(cell); - - // Adds some frequently used conditions - var conditions = []; - conditions['nocell'] = cell == null; - conditions['ncells'] = editor.graph.getSelectionCount() > 1; - conditions['notRoot'] = model.getRoot() != - model.getParent(editor.graph.getDefaultParent()); - conditions['cell'] = cell != null; - - var isCell = cell != null && editor.graph.getSelectionCount() == 1; - conditions['nonEmpty'] = isCell && childCount > 0; - conditions['expandable'] = isCell && editor.graph.isCellFoldable(cell, false); - conditions['collapsable'] = isCell && editor.graph.isCellFoldable(cell, true); - conditions['validRoot'] = isCell && editor.graph.isValidRoot(cell); - conditions['emptyValidRoot'] = conditions['validRoot'] && childCount == 0; - conditions['swimlane'] = isCell && editor.graph.isSwimlane(cell); - - // Evaluates dynamic conditions from config file - var condNodes = this.config.getElementsByTagName('condition'); - - for (var i=0; i<condNodes.length; i++) - { - var funct = mxUtils.eval(mxUtils.getTextContent(condNodes[i])); - var name = condNodes[i].getAttribute('name'); - - if (name != null && typeof(funct) == 'function') - { - conditions[name] = funct(editor, cell, evt); - } - } - - return conditions; -}; diff --git a/editor/mxDefaultToolbar.js b/editor/mxDefaultToolbar.js deleted file mode 100644 index 3f8f901..0000000 --- a/editor/mxDefaultToolbar.js +++ /dev/null @@ -1,567 +0,0 @@ -/** - * $Id: mxDefaultToolbar.js,v 1.67 2012-04-11 07:00:52 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxDefaultToolbar - * - * Toolbar for the editor. This modifies the state of the graph - * or inserts new cells upon mouse clicks. - * - * Example: - * - * Create a toolbar with a button to copy the selection into the clipboard, - * and a combo box with one action to paste the selection from the clipboard - * into the graph. - * - * (code) - * var toolbar = new mxDefaultToolbar(container, editor); - * toolbar.addItem('Copy', null, 'copy'); - * - * var combo = toolbar.addActionCombo('More actions...'); - * toolbar.addActionOption(combo, 'Paste', 'paste'); - * (end) - * - * Codec: - * - * This class uses the <mxDefaultToolbarCodec> to read configuration - * data into an existing instance. See <mxDefaultToolbarCodec> for a - * description of the configuration format. - * - * Constructor: mxDefaultToolbar - * - * Constructs a new toolbar for the given container and editor. The - * container and editor may be null if a prototypical instance for a - * <mxDefaultKeyHandlerCodec> is created. - * - * Parameters: - * - * container - DOM node that contains the toolbar. - * editor - Reference to the enclosing <mxEditor>. - */ -function mxDefaultToolbar(container, editor) -{ - this.editor = editor; - - if (container != null && - editor != null) - { - this.init(container); - } -}; - -/** - * Variable: editor - * - * Reference to the enclosing <mxEditor>. - */ -mxDefaultToolbar.prototype.editor = null; - -/** - * Variable: toolbar - * - * Holds the internal <mxToolbar>. - */ -mxDefaultToolbar.prototype.toolbar = null; - -/** - * Variable: resetHandler - * - * Reference to the function used to reset the <toolbar>. - */ -mxDefaultToolbar.prototype.resetHandler = null; - -/** - * Variable: spacing - * - * Defines the spacing between existing and new vertices in - * gridSize units when a new vertex is dropped on an existing - * cell. Default is 4 (40 pixels). - */ -mxDefaultToolbar.prototype.spacing = 4; - -/** - * Variable: connectOnDrop - * - * Specifies if elements should be connected if new cells are dropped onto - * connectable elements. Default is false. - */ -mxDefaultToolbar.prototype.connectOnDrop = false; - -/** - * Variable: init - * - * Constructs the <toolbar> for the given container and installs a listener - * that updates the <mxEditor.insertFunction> on <editor> if an item is - * selected in the toolbar. This assumes that <editor> is not null. - * - * Parameters: - * - * container - DOM node that contains the toolbar. - */ -mxDefaultToolbar.prototype.init = function(container) -{ - if (container != null) - { - this.toolbar = new mxToolbar(container); - - // Installs the insert function in the editor if an item is - // selected in the toolbar - this.toolbar.addListener(mxEvent.SELECT, - mxUtils.bind(this, function(sender, evt) - { - var funct = evt.getProperty('function'); - - if (funct != null) - { - this.editor.insertFunction = mxUtils.bind(this, function() - { - funct.apply(this, arguments); - this.toolbar.resetMode(); - }); - } - else - { - this.editor.insertFunction = null; - } - }) - ); - - // Resets the selected tool after a doubleclick or escape keystroke - this.resetHandler = mxUtils.bind(this, function() - { - if (this.toolbar != null) - { - this.toolbar.resetMode(true); - } - }); - - this.editor.graph.addListener(mxEvent.DOUBLE_CLICK, this.resetHandler); - this.editor.addListener(mxEvent.ESCAPE, this.resetHandler); - } -}; - -/** - * Function: addItem - * - * Adds a new item that executes the given action in <editor>. The title, - * icon and pressedIcon are used to display the toolbar item. - * - * Parameters: - * - * title - String that represents the title (tooltip) for the item. - * icon - URL of the icon to be used for displaying the item. - * action - Name of the action to execute when the item is clicked. - * pressed - Optional URL of the icon for the pressed state. - */ -mxDefaultToolbar.prototype.addItem = function(title, icon, action, pressed) -{ - var clickHandler = mxUtils.bind(this, function() - { - if (action != null && action.length > 0) - { - this.editor.execute(action); - } - }); - - return this.toolbar.addItem(title, icon, clickHandler, pressed); -}; - -/** - * Function: addSeparator - * - * Adds a vertical separator using the optional icon. - * - * Parameters: - * - * icon - Optional URL of the icon that represents the vertical separator. - * Default is <mxClient.imageBasePath> + '/separator.gif'. - */ -mxDefaultToolbar.prototype.addSeparator = function(icon) -{ - icon = icon || mxClient.imageBasePath + '/separator.gif'; - this.toolbar.addSeparator(icon); -}; - -/** - * Function: addCombo - * - * Helper method to invoke <mxToolbar.addCombo> on <toolbar> and return the - * resulting DOM node. - */ -mxDefaultToolbar.prototype.addCombo = function() -{ - return this.toolbar.addCombo(); -}; - -/** - * Function: addActionCombo - * - * Helper method to invoke <mxToolbar.addActionCombo> on <toolbar> using - * the given title and return the resulting DOM node. - * - * Parameters: - * - * title - String that represents the title of the combo. - */ -mxDefaultToolbar.prototype.addActionCombo = function(title) -{ - return this.toolbar.addActionCombo(title); -}; - -/** - * Function: addActionOption - * - * Binds the given action to a option with the specified label in the - * given combo. Combo is an object returned from an earlier call to - * <addCombo> or <addActionCombo>. - * - * Parameters: - * - * combo - DOM node that represents the combo box. - * title - String that represents the title of the combo. - * action - Name of the action to execute in <editor>. - */ -mxDefaultToolbar.prototype.addActionOption = function(combo, title, action) -{ - var clickHandler = mxUtils.bind(this, function() - { - this.editor.execute(action); - }); - - this.addOption(combo, title, clickHandler); -}; - -/** - * Function: addOption - * - * Helper method to invoke <mxToolbar.addOption> on <toolbar> and return - * the resulting DOM node that represents the option. - * - * Parameters: - * - * combo - DOM node that represents the combo box. - * title - String that represents the title of the combo. - * value - Object that represents the value of the option. - */ -mxDefaultToolbar.prototype.addOption = function(combo, title, value) -{ - return this.toolbar.addOption(combo, title, value); -}; - -/** - * Function: addMode - * - * Creates an item for selecting the given mode in the <editor>'s graph. - * Supported modenames are select, connect and pan. - * - * Parameters: - * - * title - String that represents the title of the item. - * icon - URL of the icon that represents the item. - * mode - String that represents the mode name to be used in - * <mxEditor.setMode>. - * pressed - Optional URL of the icon that represents the pressed state. - * funct - Optional JavaScript function that takes the <mxEditor> as the - * first and only argument that is executed after the mode has been - * selected. - */ -mxDefaultToolbar.prototype.addMode = function(title, icon, mode, pressed, funct) -{ - var clickHandler = mxUtils.bind(this, function() - { - this.editor.setMode(mode); - - if (funct != null) - { - funct(this.editor); - } - }); - - return this.toolbar.addSwitchMode(title, icon, clickHandler, pressed); -}; - -/** - * Function: addPrototype - * - * Creates an item for inserting a clone of the specified prototype cell into - * the <editor>'s graph. The ptype may either be a cell or a function that - * returns a cell. - * - * Parameters: - * - * title - String that represents the title of the item. - * icon - URL of the icon that represents the item. - * ptype - Function or object that represents the prototype cell. If ptype - * is a function then it is invoked with no arguments to create new - * instances. - * pressed - Optional URL of the icon that represents the pressed state. - * insert - Optional JavaScript function that handles an insert of the new - * cell. This function takes the <mxEditor>, new cell to be inserted, mouse - * event and optional <mxCell> under the mouse pointer as arguments. - * toggle - Optional boolean that specifies if the item can be toggled. - * Default is true. - */ -mxDefaultToolbar.prototype.addPrototype = function(title, icon, ptype, pressed, insert, toggle) -{ - // Creates a wrapper function that is in charge of constructing - // the new cell instance to be inserted into the graph - var factory = function() - { - if (typeof(ptype) == 'function') - { - return ptype(); - } - else if (ptype != null) - { - return ptype.clone(); - } - - return null; - }; - - // Defines the function for a click event on the graph - // after this item has been selected in the toolbar - var clickHandler = mxUtils.bind(this, function(evt, cell) - { - if (typeof(insert) == 'function') - { - insert(this.editor, factory(), evt, cell); - } - else - { - this.drop(factory(), evt, cell); - } - - this.toolbar.resetMode(); - mxEvent.consume(evt); - }); - - var img = this.toolbar.addMode(title, icon, clickHandler, pressed, null, toggle); - - // Creates a wrapper function that calls the click handler without - // the graph argument - var dropHandler = function(graph, evt, cell) - { - clickHandler(evt, cell); - }; - - this.installDropHandler(img, dropHandler); - - return img; -}; - -/** - * Function: drop - * - * Handles a drop from a toolbar item to the graph. The given vertex - * represents the new cell to be inserted. This invokes <insert> or - * <connect> depending on the given target cell. - * - * Parameters: - * - * vertex - <mxCell> to be inserted. - * evt - Mouse event that represents the drop. - * target - Optional <mxCell> that represents the drop target. - */ -mxDefaultToolbar.prototype.drop = function(vertex, evt, target) -{ - var graph = this.editor.graph; - var model = graph.getModel(); - - if (target == null || - model.isEdge(target) || - !this.connectOnDrop || - !graph.isCellConnectable(target)) - { - while (target != null && - !graph.isValidDropTarget(target, [vertex], evt)) - { - target = model.getParent(target); - } - - this.insert(vertex, evt, target); - } - else - { - this.connect(vertex, evt, target); - } -}; - -/** - * Function: insert - * - * Handles a drop by inserting the given vertex into the given parent cell - * or the default parent if no parent is specified. - * - * Parameters: - * - * vertex - <mxCell> to be inserted. - * evt - Mouse event that represents the drop. - * parent - Optional <mxCell> that represents the parent. - */ -mxDefaultToolbar.prototype.insert = function(vertex, evt, target) -{ - var graph = this.editor.graph; - - if (graph.canImportCell(vertex)) - { - var x = mxEvent.getClientX(evt); - var y = mxEvent.getClientY(evt); - var pt = mxUtils.convertPoint(graph.container, x, y); - - // Splits the target edge or inserts into target group - if (graph.isSplitEnabled() && - graph.isSplitTarget(target, [vertex], evt)) - { - return graph.splitEdge(target, [vertex], null, pt.x, pt.y); - } - else - { - return this.editor.addVertex(target, vertex, pt.x, pt.y); - } - } - - return null; -}; - -/** - * Function: connect - * - * Handles a drop by connecting the given vertex to the given source cell. - * - * vertex - <mxCell> to be inserted. - * evt - Mouse event that represents the drop. - * source - Optional <mxCell> that represents the source terminal. - */ -mxDefaultToolbar.prototype.connect = function(vertex, evt, source) -{ - var graph = this.editor.graph; - var model = graph.getModel(); - - if (source != null && - graph.isCellConnectable(vertex) && - graph.isEdgeValid(null, source, vertex)) - { - var edge = null; - - model.beginUpdate(); - try - { - var geo = model.getGeometry(source); - var g = model.getGeometry(vertex).clone(); - - // Moves the vertex away from the drop target that will - // be used as the source for the new connection - g.x = geo.x + (geo.width - g.width) / 2; - g.y = geo.y + (geo.height - g.height) / 2; - - var step = this.spacing * graph.gridSize; - var dist = model.getDirectedEdgeCount(source, true) * 20; - - if (this.editor.horizontalFlow) - { - g.x += (g.width + geo.width) / 2 + step + dist; - } - else - { - g.y += (g.height + geo.height) / 2 + step + dist; - } - - vertex.setGeometry(g); - - // Fires two add-events with the code below - should be fixed - // to only fire one add event for both inserts - var parent = model.getParent(source); - graph.addCell(vertex, parent); - graph.constrainChild(vertex); - - // Creates the edge using the editor instance and calls - // the second function that fires an add event - edge = this.editor.createEdge(source, vertex); - - if (model.getGeometry(edge) == null) - { - var edgeGeometry = new mxGeometry(); - edgeGeometry.relative = true; - - model.setGeometry(edge, edgeGeometry); - } - - graph.addEdge(edge, parent, source, vertex); - } - finally - { - model.endUpdate(); - } - - graph.setSelectionCells([vertex, edge]); - graph.scrollCellToVisible(vertex); - } -}; - -/** - * Function: installDropHandler - * - * Makes the given img draggable using the given function for handling a - * drop event. - * - * Parameters: - * - * img - DOM node that represents the image. - * dropHandler - Function that handles a drop of the image. - */ -mxDefaultToolbar.prototype.installDropHandler = function (img, dropHandler) -{ - var sprite = document.createElement('img'); - sprite.setAttribute('src', img.getAttribute('src')); - - // Handles delayed loading of the images - var loader = mxUtils.bind(this, function(evt) - { - // Preview uses the image node with double size. Later this can be - // changed to use a separate preview and guides, but for this the - // dropHandler must use the additional x- and y-arguments and the - // dragsource which makeDraggable returns much be configured to - // use guides via mxDragSource.isGuidesEnabled. - sprite.style.width = (2 * img.offsetWidth) + 'px'; - sprite.style.height = (2 * img.offsetHeight) + 'px'; - - mxUtils.makeDraggable(img, this.editor.graph, dropHandler, - sprite); - mxEvent.removeListener(sprite, 'load', loader); - }); - - if (mxClient.IS_IE) - { - loader(); - } - else - { - mxEvent.addListener(sprite, 'load', loader); - } -}; - -/** - * Function: destroy - * - * Destroys the <toolbar> associated with this object and removes all - * installed listeners. This does normally not need to be called, the - * <toolbar> is destroyed automatically when the window unloads (in IE) by - * <mxEditor>. - */ -mxDefaultToolbar.prototype.destroy = function () -{ - if (this.resetHandler != null) - { - this.editor.graph.removeListener('dblclick', this.resetHandler); - this.editor.removeListener('escape', this.resetHandler); - this.resetHandler = null; - } - - if (this.toolbar != null) - { - this.toolbar.destroy(); - this.toolbar = null; - } -}; diff --git a/editor/mxEditor.js b/editor/mxEditor.js deleted file mode 100644 index 9c57a9c..0000000 --- a/editor/mxEditor.js +++ /dev/null @@ -1,3220 +0,0 @@ -/** - * $Id: mxEditor.js,v 1.231 2012-12-03 18:02:25 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxEditor - * - * Extends <mxEventSource> to implement a application wrapper for a graph that - * adds <actions>, I/O using <mxCodec>, auto-layout using <mxLayoutManager>, - * command history using <undoManager>, and standard dialogs and widgets, eg. - * properties, help, outline, toolbar, and popupmenu. It also adds <templates> - * to be used as cells in toolbars, auto-validation using the <validation> - * flag, attribute cycling using <cycleAttributeValues>, higher-level events - * such as <root>, and backend integration using <urlPost>, <urlImage>, - * <urlInit>, <urlNotify> and <urlPoll>. - * - * Actions: - * - * Actions are functions stored in the <actions> array under their names. The - * functions take the <mxEditor> as the first, and an optional <mxCell> as the - * second argument and are invoked using <execute>. Any additional arguments - * passed to execute are passed on to the action as-is. - * - * A list of built-in actions is available in the <addActions> description. - * - * Read/write Diagrams: - * - * To read a diagram from an XML string, for example from a textfield within the - * page, the following code is used: - * - * (code) - * var doc = mxUtils.parseXML(xmlString); - * var node = doc.documentElement; - * editor.readGraphModel(node); - * (end) - * - * For reading a diagram from a remote location, use the <open> method. - * - * To save diagrams in XML on a server, you can set the <urlPost> variable. - * This variable will be used in <getUrlPost> to construct a URL for the post - * request that is issued in the <save> method. The post request contains the - * XML representation of the diagram as returned by <writeGraphModel> in the - * xml parameter. - * - * On the server side, the post request is processed using standard - * technologies such as Java Servlets, CGI, .NET or ASP. - * - * Here are some examples of processing a post request in various languages. - * - * - Java: URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "
") - * - * Note that the linefeeds should only be replaced if the XML is - * processed in Java, for example when creating an image, but not - * if the XML is passed back to the client-side. - * - * - .NET: HttpUtility.UrlDecode(context.Request.Params["xml"]) - * - PHP: urldecode($_POST["xml"]) - * - * Creating images: - * - * A backend (Java, PHP or C#) is required for creating images. The - * distribution contains an example for each backend (ImageHandler.java, - * ImageHandler.cs and graph.php). More information about using a backend - * to create images can be found in the readme.html files. Note that the - * preview is implemented using VML/SVG in the browser and does not require - * a backend. The backend is only required to creates images (bitmaps). - * - * Special characters: - * - * Note There are five characters that should always appear in XML content as - * escapes, so that they do not interact with the syntax of the markup. These - * are part of the language for all documents based on XML and for HTML. - * - * - < (<) - * - > (>) - * - & (&) - * - " (") - * - ' (') - * - * Although it is part of the XML language, ' is not defined in HTML. - * For this reason the XHTML specification recommends instead the use of - * ' if text may be passed to a HTML user agent. - * - * If you are having problems with special characters on the server-side then - * you may want to try the <escapePostData> flag. - * - * For converting decimal escape sequences inside strings, a user has provided - * us with the following function: - * - * (code) - * function html2js(text) - * { - * var entitySearch = /&#[0-9]+;/; - * var entity; - * - * while (entity = entitySearch.exec(text)) - * { - * var charCode = entity[0].substring(2, entity[0].length -1); - * text = text.substring(0, entity.index) - * + String.fromCharCode(charCode) - * + text.substring(entity.index + entity[0].length); - * } - * - * return text; - * } - * (end) - * - * Otherwise try using hex escape sequences and the built-in unescape function - * for converting such strings. - * - * Local Files: - * - * For saving and opening local files, no standardized method exists that - * works across all browsers. The recommended way of dealing with local files - * is to create a backend that streams the XML data back to the browser (echo) - * as an attachment so that a Save-dialog is displayed on the client-side and - * the file can be saved to the local disk. - * - * For example, in PHP the code that does this looks as follows. - * - * (code) - * $xml = stripslashes($_POST["xml"]); - * header("Content-Disposition: attachment; filename=\"diagram.xml\""); - * echo($xml); - * (end) - * - * To open a local file, the file should be uploaded via a form in the browser - * and then opened from the server in the editor. - * - * Cell Properties: - * - * The properties displayed in the properties dialog are the attributes and - * values of the cell's user object, which is an XML node. The XML node is - * defined in the templates section of the config file. - * - * The templates are stored in <mxEditor.templates> and contain cells which - * are cloned at insertion time to create new vertices by use of drag and - * drop from the toolbar. Each entry in the toolbar for adding a new vertex - * must refer to an existing template. - * - * In the following example, the task node is a business object and only the - * mxCell node and its mxGeometry child contain graph information: - * - * (code) - * <Task label="Task" description=""> - * <mxCell vertex="true"> - * <mxGeometry as="geometry" width="72" height="32"/> - * </mxCell> - * </Task> - * (end) - * - * The idea is that the XML representation is inverse from the in-memory - * representation: The outer XML node is the user object and the inner node is - * the cell. This means the user object of the cell is the Task node with no - * children for the above example: - * - * (code) - * <Task label="Task" description=""/> - * (end) - * - * The Task node can have any tag name, attributes and child nodes. The - * <mxCodec> will use the XML hierarchy as the user object, while removing the - * "known annotations", such as the mxCell node. At save-time the cell data - * will be "merged" back into the user object. The user object is only modified - * via the properties dialog during the lifecycle of the cell. - * - * In the default implementation of <createProperties>, the user object's - * attributes are put into a form for editing. Attributes are changed using - * the <mxCellAttributeChange> action in the model. The dialog can be replaced - * by overriding the <createProperties> hook or by replacing the showProperties - * action in <actions>. Alternatively, the entry in the config file's popupmenu - * section can be modified to invoke a different action. - * - * If you want to displey the properties dialog on a doubleclick, you can set - * <mxEditor.dblClickAction> to showProperties as follows: - * - * (code) - * editor.dblClickAction = 'showProperties'; - * (end) - * - * Popupmenu and Toolbar: - * - * The toolbar and popupmenu are typically configured using the respective - * sections in the config file, that is, the popupmenu is defined as follows: - * - * (code) - * <mxEditor> - * <mxDefaultPopupMenu as="popupHandler"> - * <add as="cut" action="cut" icon="images/cut.gif"/> - * ... - * (end) - * - * New entries can be added to the toolbar by inserting an add-node into the - * above configuration. Existing entries may be removed and changed by - * modifying or removing the respective entries in the configuration. - * The configuration is read by the <mxDefaultPopupMenuCodec>, the format of the - * configuration is explained in <mxDefaultPopupMenu.decode>. - * - * The toolbar is defined in the mxDefaultToolbar section. Items can be added - * and removed in this section. - * - * (code) - * <mxEditor> - * <mxDefaultToolbar> - * <add as="save" action="save" icon="images/save.gif"/> - * <add as="Swimlane" template="swimlane" icon="images/swimlane.gif"/> - * ... - * (end) - * - * The format of the configuration is described in - * <mxDefaultToolbarCodec.decode>. - * - * Ids: - * - * For the IDs, there is an implicit behaviour in <mxCodec>: It moves the Id - * from the cell to the user object at encoding time and vice versa at decoding - * time. For example, if the Task node from above has an id attribute, then - * the <mxCell.id> of the corresponding cell will have this value. If there - * is no Id collision in the model, then the cell may be retrieved using this - * Id with the <mxGraphModel.getCell> function. If there is a collision, a new - * Id will be created for the cell using <mxGraphModel.createId>. At encoding - * time, this new Id will replace the value previously stored under the id - * attribute in the Task node. - * - * See <mxEditorCodec>, <mxDefaultToolbarCodec> and <mxDefaultPopupMenuCodec> - * for information about configuring the editor and user interface. - * - * Programmatically inserting cells: - * - * For inserting a new cell, say, by clicking a button in the document, - * the following code can be used. This requires an reference to the editor. - * - * (code) - * var userObject = new Object(); - * var parent = editor.graph.getDefaultParent(); - * var model = editor.graph.model; - * model.beginUpdate(); - * try - * { - * editor.graph.insertVertex(parent, null, userObject, 20, 20, 80, 30); - * } - * finally - * { - * model.endUpdate(); - * } - * (end) - * - * If a template cell from the config file should be inserted, then a clone - * of the template can be created as follows. The clone is then inserted using - * the add function instead of addVertex. - * - * (code) - * var template = editor.templates['task']; - * var clone = editor.graph.model.cloneCell(template); - * (end) - * - * Resources: - * - * resources/editor - Language resources for mxEditor - * - * Callback: onInit - * - * Called from within the constructor. In the callback, - * "this" refers to the editor instance. - * - * Cookie: mxgraph=seen - * - * Set when the editor is started. Never expires. Use - * <resetFirstTime> to reset this cookie. This cookie - * only exists if <onInit> is implemented. - * - * Event: mxEvent.OPEN - * - * Fires after a file was opened in <open>. The <code>filename</code> property - * contains the filename that was used. The same value is also available in - * <filename>. - * - * Event: mxEvent.SAVE - * - * Fires after the current file was saved in <save>. The <code>url</code> - * property contains the URL that was used for saving. - * - * Event: mxEvent.POST - * - * Fires if a successful response was received in <postDiagram>. The - * <code>request</code> property contains the <mxXmlRequest>, the - * <code>url</code> and <code>data</code> properties contain the URL and the - * data that were used in the post request. - * - * Event: mxEvent.ROOT - * - * Fires when the current root has changed, or when the title of the current - * root has changed. This event has no properties. - * - * Event: mxEvent.SESSION - * - * Fires when anything in the session has changed. The <code>session</code> - * property contains the respective <mxSession>. - * - * Event: mxEvent.BEFORE_ADD_VERTEX - * - * Fires before a vertex is added in <addVertex>. The <code>vertex</code> - * property contains the new vertex and the <code>parent</code> property - * contains its parent. - * - * Event: mxEvent.ADD_VERTEX - * - * Fires between begin- and endUpdate in <addVertex>. The <code>vertex</code> - * property contains the vertex that is being inserted. - * - * Event: mxEvent.AFTER_ADD_VERTEX - * - * Fires after a vertex was inserted and selected in <addVertex>. The - * <code>vertex</code> property contains the new vertex. - * - * Example: - * - * For starting an in-place edit after a new vertex has been added to the - * graph, the following code can be used. - * - * (code) - * editor.addListener(mxEvent.AFTER_ADD_VERTEX, function(sender, evt) - * { - * var vertex = evt.getProperty('vertex'); - * - * if (editor.graph.isCellEditable(vertex)) - * { - * editor.graph.startEditingAtCell(vertex); - * } - * }); - * (end) - * - * Event: mxEvent.ESCAPE - * - * Fires when the escape key is pressed. The <code>event</code> property - * contains the key event. - * - * Constructor: mxEditor - * - * Constructs a new editor. This function invokes the <onInit> callback - * upon completion. - * - * Example: - * - * (code) - * var config = mxUtils.load('config/diagrameditor.xml').getDocumentElement(); - * var editor = new mxEditor(config); - * (end) - * - * Parameters: - * - * config - Optional XML node that contains the configuration. - */ -function mxEditor(config) -{ - this.actions = []; - this.addActions(); - - // Executes the following only if a document has been instanciated. - // That is, don't execute when the editorcodec is setup. - if (document.body != null) - { - // Defines instance fields - this.cycleAttributeValues = []; - this.popupHandler = new mxDefaultPopupMenu(); - this.undoManager = new mxUndoManager(); - - // Creates the graph and toolbar without the containers - this.graph = this.createGraph(); - this.toolbar = this.createToolbar(); - - // Creates the global keyhandler (requires graph instance) - this.keyHandler = new mxDefaultKeyHandler(this); - - // Configures the editor using the URI - // which was passed to the ctor - this.configure(config); - - // Assigns the swimlaneIndicatorColorAttribute on the graph - this.graph.swimlaneIndicatorColorAttribute = this.cycleAttributeName; - - // Initializes the session if the urlInit - // member field of this editor is set. - if (!mxClient.IS_LOCAL && this.urlInit != null) - { - this.session = this.createSession(); - } - - // Checks ifthe <onInit> hook has been set - if (this.onInit != null) - { - // Invokes the <onInit> hook - this.onInit(); - } - - // Automatic deallocation of memory - if (mxClient.IS_IE) - { - mxEvent.addListener(window, 'unload', mxUtils.bind(this, function() - { - this.destroy(); - })); - } - } -}; - -/** - * Installs the required language resources at class - * loading time. - */ -if (mxLoadResources) -{ - mxResources.add(mxClient.basePath+'/resources/editor'); -} - -/** - * Extends mxEventSource. - */ -mxEditor.prototype = new mxEventSource(); -mxEditor.prototype.constructor = mxEditor; - -/** - * Group: Controls and Handlers - */ - -/** - * Variable: askZoomResource - * - * Specifies the resource key for the zoom dialog. If the resource for this - * key does not exist then the value is used as the error message. Default - * is 'askZoom'. - */ -mxEditor.prototype.askZoomResource = (mxClient.language != 'none') ? 'askZoom' : ''; - -/** - * Variable: lastSavedResource - * - * Specifies the resource key for the last saved info. If the resource for - * this key does not exist then the value is used as the error message. - * Default is 'lastSaved'. - */ -mxEditor.prototype.lastSavedResource = (mxClient.language != 'none') ? 'lastSaved' : ''; - -/** - * Variable: currentFileResource - * - * Specifies the resource key for the current file info. If the resource for - * this key does not exist then the value is used as the error message. - * Default is 'lastSaved'. - */ -mxEditor.prototype.currentFileResource = (mxClient.language != 'none') ? 'currentFile' : ''; - -/** - * Variable: propertiesResource - * - * Specifies the resource key for the properties window title. If the - * resource for this key does not exist then the value is used as the - * error message. Default is 'properties'. - */ -mxEditor.prototype.propertiesResource = (mxClient.language != 'none') ? 'properties' : ''; - -/** - * Variable: tasksResource - * - * Specifies the resource key for the tasks window title. If the - * resource for this key does not exist then the value is used as the - * error message. Default is 'tasks'. - */ -mxEditor.prototype.tasksResource = (mxClient.language != 'none') ? 'tasks' : ''; - -/** - * Variable: helpResource - * - * Specifies the resource key for the help window title. If the - * resource for this key does not exist then the value is used as the - * error message. Default is 'help'. - */ -mxEditor.prototype.helpResource = (mxClient.language != 'none') ? 'help' : ''; - -/** - * Variable: outlineResource - * - * Specifies the resource key for the outline window title. If the - * resource for this key does not exist then the value is used as the - * error message. Default is 'outline'. - */ -mxEditor.prototype.outlineResource = (mxClient.language != 'none') ? 'outline' : ''; - -/** - * Variable: outline - * - * Reference to the <mxWindow> that contains the outline. The <mxOutline> - * is stored in outline.outline. - */ -mxEditor.prototype.outline = null; - -/** - * Variable: graph - * - * Holds a <mxGraph> for displaying the diagram. The graph - * is created in <setGraphContainer>. - */ -mxEditor.prototype.graph = null; - -/** - * Variable: graphRenderHint - * - * Holds the render hint used for creating the - * graph in <setGraphContainer>. See <mxGraph>. - * Default is null. - */ -mxEditor.prototype.graphRenderHint = null; - -/** - * Variable: toolbar - * - * Holds a <mxDefaultToolbar> for displaying the toolbar. The - * toolbar is created in <setToolbarContainer>. - */ -mxEditor.prototype.toolbar = null; - -/** - * Variable: session - * - * Holds a <mxSession> instance associated with this editor. - */ -mxEditor.prototype.session = null; - -/** - * Variable: status - * - * DOM container that holds the statusbar. Default is null. - * Use <setStatusContainer> to set this value. - */ -mxEditor.prototype.status = null; - -/** - * Variable: popupHandler - * - * Holds a <mxDefaultPopupMenu> for displaying - * popupmenus. - */ -mxEditor.prototype.popupHandler = null; - -/** - * Variable: undoManager - * - * Holds an <mxUndoManager> for the command history. - */ -mxEditor.prototype.undoManager = null; - -/** - * Variable: keyHandler - * - * Holds a <mxDefaultKeyHandler> for handling keyboard events. - * The handler is created in <setGraphContainer>. - */ -mxEditor.prototype.keyHandler = null; - -/** - * Group: Actions and Options - */ - -/** - * Variable: actions - * - * Maps from actionnames to actions, which are functions taking - * the editor and the cell as arguments. Use <addAction> - * to add or replace an action and <execute> to execute an action - * by name, passing the cell to be operated upon as the second - * argument. - */ -mxEditor.prototype.actions = null; - -/** - * Variable: dblClickAction - * - * Specifies the name of the action to be executed - * when a cell is double clicked. Default is edit. - * - * To handle a singleclick, use the following code. - * - * (code) - * editor.graph.addListener(mxEvent.CLICK, function(sender, evt) - * { - * var e = evt.getProperty('event'); - * var cell = evt.getProperty('cell'); - * - * if (cell != null && !e.isConsumed()) - * { - * // Do something useful with cell... - * e.consume(); - * } - * }); - * (end) - */ -mxEditor.prototype.dblClickAction = 'edit'; - -/** - * Variable: swimlaneRequired - * - * Specifies if new cells must be inserted - * into an existing swimlane. Otherwise, cells - * that are not swimlanes can be inserted as - * top-level cells. Default is false. - */ -mxEditor.prototype.swimlaneRequired = false; - -/** - * Variable: disableContextMenu - * - * Specifies if the context menu should be disabled in the graph container. - * Default is true. - */ -mxEditor.prototype.disableContextMenu = true; - -/** - * Group: Templates - */ - -/** - * Variable: insertFunction - * - * Specifies the function to be used for inserting new - * cells into the graph. This is assigned from the - * <mxDefaultToolbar> if a vertex-tool is clicked. - */ -mxEditor.prototype.insertFunction = null; - -/** - * Variable: forcedInserting - * - * Specifies if a new cell should be inserted on a single - * click even using <insertFunction> if there is a cell - * under the mousepointer, otherwise the cell under the - * mousepointer is selected. Default is false. - */ -mxEditor.prototype.forcedInserting = false; - -/** - * Variable: templates - * - * Maps from names to protoype cells to be used - * in the toolbar for inserting new cells into - * the diagram. - */ -mxEditor.prototype.templates = null; - -/** - * Variable: defaultEdge - * - * Prototype edge cell that is used for creating - * new edges. - */ -mxEditor.prototype.defaultEdge = null; - -/** - * Variable: defaultEdgeStyle - * - * Specifies the edge style to be returned in <getEdgeStyle>. - * Default is null. - */ -mxEditor.prototype.defaultEdgeStyle = null; - -/** - * Variable: defaultGroup - * - * Prototype group cell that is used for creating - * new groups. - */ -mxEditor.prototype.defaultGroup = null; - -/** - * Variable: graphRenderHint - * - * Default size for the border of new groups. If null, - * then then <mxGraph.gridSize> is used. Default is - * null. - */ -mxEditor.prototype.groupBorderSize = null; - -/** - * Group: Backend Integration - */ - -/** - * Variable: filename - * - * Contains the URL of the last opened file as a string. - * Default is null. - */ -mxEditor.prototype.filename = null; - -/** - * Variable: lineFeed - * - * Character to be used for encoding linefeeds in <save>. Default is '
'. - */ -mxEditor.prototype.linefeed = '
'; - -/** - * Variable: postParameterName - * - * Specifies if the name of the post parameter that contains the diagram - * data in a post request to the server. Default is xml. - */ -mxEditor.prototype.postParameterName = 'xml'; - -/** - * Variable: escapePostData - * - * Specifies if the data in the post request for saving a diagram - * should be converted using encodeURIComponent. Default is true. - */ -mxEditor.prototype.escapePostData = true; - -/** - * Variable: urlPost - * - * Specifies the URL to be used for posting the diagram - * to a backend in <save>. - */ -mxEditor.prototype.urlPost = null; - -/** - * Variable: urlImage - * - * Specifies the URL to be used for creating a bitmap of - * the graph in the image action. - */ -mxEditor.prototype.urlImage = null; - -/** - * Variable: urlInit - * - * Specifies the URL to be used for initializing the session. - */ -mxEditor.prototype.urlInit = null; - -/** - * Variable: urlNotify - * - * Specifies the URL to be used for notifying the backend - * in the session. - */ -mxEditor.prototype.urlNotify = null; - -/** - * Variable: urlPoll - * - * Specifies the URL to be used for polling in the session. - */ -mxEditor.prototype.urlPoll = null; - -/** - * Group: Autolayout - */ - -/** - * Variable: horizontalFlow - * - * Specifies the direction of the flow - * in the diagram. This is used in the - * layout algorithms. Default is false, - * ie. vertical flow. - */ -mxEditor.prototype.horizontalFlow = false; - -/** - * Variable: layoutDiagram - * - * Specifies if the top-level elements in the - * diagram should be layed out using a vertical - * or horizontal stack depending on the setting - * of <horizontalFlow>. The spacing between the - * swimlanes is specified by <swimlaneSpacing>. - * Default is false. - * - * If the top-level elements are swimlanes, then - * the intra-swimlane layout is activated by - * the <layoutSwimlanes> switch. - */ -mxEditor.prototype.layoutDiagram = false; - -/** - * Variable: swimlaneSpacing - * - * Specifies the spacing between swimlanes if - * automatic layout is turned on in - * <layoutDiagram>. Default is 0. - */ -mxEditor.prototype.swimlaneSpacing = 0; - -/** - * Variable: maintainSwimlanes - * - * Specifies if the swimlanes should be kept at the same - * width or height depending on the setting of - * <horizontalFlow>. Default is false. - * - * For horizontal flows, all swimlanes - * have the same height and for vertical flows, all swimlanes - * have the same width. Furthermore, the swimlanes are - * automatically "stacked" if <layoutDiagram> is true. - */ -mxEditor.prototype.maintainSwimlanes = false; - -/** - * Variable: layoutSwimlanes - * - * Specifies if the children of swimlanes should - * be layed out, either vertically or horizontally - * depending on <horizontalFlow>. - * Default is false. - */ -mxEditor.prototype.layoutSwimlanes = false; - -/** - * Group: Attribute Cycling - */ - -/** - * Variable: cycleAttributeValues - * - * Specifies the attribute values to be cycled when - * inserting new swimlanes. Default is an empty - * array. - */ -mxEditor.prototype.cycleAttributeValues = null; - -/** - * Variable: cycleAttributeIndex - * - * Index of the last consumed attribute index. If a new - * swimlane is inserted, then the <cycleAttributeValues> - * at this index will be used as the value for - * <cycleAttributeName>. Default is 0. - */ -mxEditor.prototype.cycleAttributeIndex = 0; - -/** - * Variable: cycleAttributeName - * - * Name of the attribute to be assigned a <cycleAttributeValues> - * when inserting new swimlanes. Default is fillColor. - */ -mxEditor.prototype.cycleAttributeName = 'fillColor'; - -/** - * Group: Windows - */ - -/** - * Variable: tasks - * - * Holds the <mxWindow> created in <showTasks>. - */ -mxEditor.prototype.tasks = null; - -/** - * Variable: tasksWindowImage - * - * Icon for the tasks window. - */ -mxEditor.prototype.tasksWindowImage = null; - -/** - * Variable: tasksTop - * - * Specifies the top coordinate of the tasks window in pixels. - * Default is 20. - */ -mxEditor.prototype.tasksTop = 20; - -/** - * Variable: help - * - * Holds the <mxWindow> created in <showHelp>. - */ -mxEditor.prototype.help = null; - -/** - * Variable: helpWindowImage - * - * Icon for the help window. - */ -mxEditor.prototype.helpWindowImage = null; - -/** - * Variable: urlHelp - * - * Specifies the URL to be used for the contents of the - * Online Help window. This is usually specified in the - * resources file under urlHelp for language-specific - * online help support. - */ -mxEditor.prototype.urlHelp = null; - -/** - * Variable: helpWidth - * - * Specifies the width of the help window in pixels. - * Default is 300. - */ -mxEditor.prototype.helpWidth = 300; - -/** - * Variable: helpWidth - * - * Specifies the width of the help window in pixels. - * Default is 260. - */ -mxEditor.prototype.helpHeight = 260; - -/** - * Variable: propertiesWidth - * - * Specifies the width of the properties window in pixels. - * Default is 240. - */ -mxEditor.prototype.propertiesWidth = 240; - -/** - * Variable: propertiesHeight - * - * Specifies the height of the properties window in pixels. - * If no height is specified then the window will be automatically - * sized to fit its contents. Default is null. - */ -mxEditor.prototype.propertiesHeight = null; - -/** - * Variable: movePropertiesDialog - * - * Specifies if the properties dialog should be automatically - * moved near the cell it is displayed for, otherwise the - * dialog is not moved. This value is only taken into - * account if the dialog is already visible. Default is false. - */ -mxEditor.prototype.movePropertiesDialog = false; - -/** - * Variable: validating - * - * Specifies if <mxGraph.validateGraph> should automatically be invoked after - * each change. Default is false. - */ -mxEditor.prototype.validating = false; - -/** - * Variable: modified - * - * True if the graph has been modified since it was last saved. - */ -mxEditor.prototype.modified = false; - -/** - * Function: isModified - * - * Returns <modified>. - */ -mxEditor.prototype.isModified = function () -{ - return this.modified; -}; - -/** - * Function: setModified - * - * Sets <modified> to the specified boolean value. - */ -mxEditor.prototype.setModified = function (value) -{ - this.modified = value; -}; - -/** - * Function: addActions - * - * Adds the built-in actions to the editor instance. - * - * save - Saves the graph using <urlPost>. - * print - Shows the graph in a new print preview window. - * show - Shows the graph in a new window. - * exportImage - Shows the graph as a bitmap image using <getUrlImage>. - * refresh - Refreshes the graph's display. - * cut - Copies the current selection into the clipboard - * and removes it from the graph. - * copy - Copies the current selection into the clipboard. - * paste - Pastes the clipboard into the graph. - * delete - Removes the current selection from the graph. - * group - Puts the current selection into a new group. - * ungroup - Removes the selected groups and selects the children. - * undo - Undoes the last change on the graph model. - * redo - Redoes the last change on the graph model. - * zoom - Sets the zoom via a dialog. - * zoomIn - Zooms into the graph. - * zoomOut - Zooms out of the graph - * actualSize - Resets the scale and translation on the graph. - * fit - Changes the scale so that the graph fits into the window. - * showProperties - Shows the properties dialog. - * selectAll - Selects all cells. - * selectNone - Clears the selection. - * selectVertices - Selects all vertices. - * selectEdges = Selects all edges. - * edit - Starts editing the current selection cell. - * enterGroup - Drills down into the current selection cell. - * exitGroup - Moves up in the drilling hierachy - * home - Moves to the topmost parent in the drilling hierarchy - * selectPrevious - Selects the previous cell. - * selectNext - Selects the next cell. - * selectParent - Selects the parent of the selection cell. - * selectChild - Selects the first child of the selection cell. - * collapse - Collapses the currently selected cells. - * expand - Expands the currently selected cells. - * bold - Toggle bold text style. - * italic - Toggle italic text style. - * underline - Toggle underline text style. - * shadow - Toggle shadow text style. - * alignCellsLeft - Aligns the selection cells at the left. - * alignCellsCenter - Aligns the selection cells in the center. - * alignCellsRight - Aligns the selection cells at the right. - * alignCellsTop - Aligns the selection cells at the top. - * alignCellsMiddle - Aligns the selection cells in the middle. - * alignCellsBottom - Aligns the selection cells at the bottom. - * alignFontLeft - Sets the horizontal text alignment to left. - * alignFontCenter - Sets the horizontal text alignment to center. - * alignFontRight - Sets the horizontal text alignment to right. - * alignFontTop - Sets the vertical text alignment to top. - * alignFontMiddle - Sets the vertical text alignment to middle. - * alignFontBottom - Sets the vertical text alignment to bottom. - * toggleTasks - Shows or hides the tasks window. - * toggleHelp - Shows or hides the help window. - * toggleOutline - Shows or hides the outline window. - * toggleConsole - Shows or hides the console window. - */ -mxEditor.prototype.addActions = function () -{ - this.addAction('save', function(editor) - { - editor.save(); - }); - - this.addAction('print', function(editor) - { - var preview = new mxPrintPreview(editor.graph, 1); - preview.open(); - }); - - this.addAction('show', function(editor) - { - mxUtils.show(editor.graph, null, 10, 10); - }); - - this.addAction('exportImage', function(editor) - { - var url = editor.getUrlImage(); - - if (url == null || mxClient.IS_LOCAL) - { - editor.execute('show'); - } - else - { - var node = mxUtils.getViewXml(editor.graph, 1); - var xml = mxUtils.getXml(node, '\n'); - - mxUtils.submit(url, editor.postParameterName + '=' + - encodeURIComponent(xml), document, '_blank'); - } - }); - - this.addAction('refresh', function(editor) - { - editor.graph.refresh(); - }); - - this.addAction('cut', function(editor) - { - if (editor.graph.isEnabled()) - { - mxClipboard.cut(editor.graph); - } - }); - - this.addAction('copy', function(editor) - { - if (editor.graph.isEnabled()) - { - mxClipboard.copy(editor.graph); - } - }); - - this.addAction('paste', function(editor) - { - if (editor.graph.isEnabled()) - { - mxClipboard.paste(editor.graph); - } - }); - - this.addAction('delete', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.removeCells(); - } - }); - - this.addAction('group', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setSelectionCell(editor.groupCells()); - } - }); - - this.addAction('ungroup', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setSelectionCells(editor.graph.ungroupCells()); - } - }); - - this.addAction('removeFromParent', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.removeCellsFromParent(); - } - }); - - this.addAction('undo', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.undo(); - } - }); - - this.addAction('redo', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.redo(); - } - }); - - this.addAction('zoomIn', function(editor) - { - editor.graph.zoomIn(); - }); - - this.addAction('zoomOut', function(editor) - { - editor.graph.zoomOut(); - }); - - this.addAction('actualSize', function(editor) - { - editor.graph.zoomActual(); - }); - - this.addAction('fit', function(editor) - { - editor.graph.fit(); - }); - - this.addAction('showProperties', function(editor, cell) - { - editor.showProperties(cell); - }); - - this.addAction('selectAll', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectAll(); - } - }); - - this.addAction('selectNone', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.clearSelection(); - } - }); - - this.addAction('selectVertices', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectVertices(); - } - }); - - this.addAction('selectEdges', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectEdges(); - } - }); - - this.addAction('edit', function(editor, cell) - { - if (editor.graph.isEnabled() && - editor.graph.isCellEditable(cell)) - { - editor.graph.startEditingAtCell(cell); - } - }); - - this.addAction('toBack', function(editor, cell) - { - if (editor.graph.isEnabled()) - { - editor.graph.orderCells(true); - } - }); - - this.addAction('toFront', function(editor, cell) - { - if (editor.graph.isEnabled()) - { - editor.graph.orderCells(false); - } - }); - - this.addAction('enterGroup', function(editor, cell) - { - editor.graph.enterGroup(cell); - }); - - this.addAction('exitGroup', function(editor) - { - editor.graph.exitGroup(); - }); - - this.addAction('home', function(editor) - { - editor.graph.home(); - }); - - this.addAction('selectPrevious', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectPreviousCell(); - } - }); - - this.addAction('selectNext', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectNextCell(); - } - }); - - this.addAction('selectParent', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectParentCell(); - } - }); - - this.addAction('selectChild', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.selectChildCell(); - } - }); - - this.addAction('collapse', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.foldCells(true); - } - }); - - this.addAction('collapseAll', function(editor) - { - if (editor.graph.isEnabled()) - { - var cells = editor.graph.getChildVertices(); - editor.graph.foldCells(true, false, cells); - } - }); - - this.addAction('expand', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.foldCells(false); - } - }); - - this.addAction('expandAll', function(editor) - { - if (editor.graph.isEnabled()) - { - var cells = editor.graph.getChildVertices(); - editor.graph.foldCells(false, false, cells); - } - }); - - this.addAction('bold', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.toggleCellStyleFlags( - mxConstants.STYLE_FONTSTYLE, - mxConstants.FONT_BOLD); - } - }); - - this.addAction('italic', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.toggleCellStyleFlags( - mxConstants.STYLE_FONTSTYLE, - mxConstants.FONT_ITALIC); - } - }); - - this.addAction('underline', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.toggleCellStyleFlags( - mxConstants.STYLE_FONTSTYLE, - mxConstants.FONT_UNDERLINE); - } - }); - - this.addAction('shadow', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.toggleCellStyleFlags( - mxConstants.STYLE_FONTSTYLE, - mxConstants.FONT_SHADOW); - } - }); - - this.addAction('alignCellsLeft', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_LEFT); - } - }); - - this.addAction('alignCellsCenter', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_CENTER); - } - }); - - this.addAction('alignCellsRight', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_RIGHT); - } - }); - - this.addAction('alignCellsTop', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_TOP); - } - }); - - this.addAction('alignCellsMiddle', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_MIDDLE); - } - }); - - this.addAction('alignCellsBottom', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.alignCells(mxConstants.ALIGN_BOTTOM); - } - }); - - this.addAction('alignFontLeft', function(editor) - { - - editor.graph.setCellStyles( - mxConstants.STYLE_ALIGN, - mxConstants.ALIGN_LEFT); - }); - - this.addAction('alignFontCenter', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setCellStyles( - mxConstants.STYLE_ALIGN, - mxConstants.ALIGN_CENTER); - } - }); - - this.addAction('alignFontRight', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setCellStyles( - mxConstants.STYLE_ALIGN, - mxConstants.ALIGN_RIGHT); - } - }); - - this.addAction('alignFontTop', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setCellStyles( - mxConstants.STYLE_VERTICAL_ALIGN, - mxConstants.ALIGN_TOP); - } - }); - - this.addAction('alignFontMiddle', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setCellStyles( - mxConstants.STYLE_VERTICAL_ALIGN, - mxConstants.ALIGN_MIDDLE); - } - }); - - this.addAction('alignFontBottom', function(editor) - { - if (editor.graph.isEnabled()) - { - editor.graph.setCellStyles( - mxConstants.STYLE_VERTICAL_ALIGN, - mxConstants.ALIGN_BOTTOM); - } - }); - - this.addAction('zoom', function(editor) - { - var current = editor.graph.getView().scale*100; - var scale = parseFloat(mxUtils.prompt( - mxResources.get(editor.askZoomResource) || - editor.askZoomResource, - current))/100; - - if (!isNaN(scale)) - { - editor.graph.getView().setScale(scale); - } - }); - - this.addAction('toggleTasks', function(editor) - { - if (editor.tasks != null) - { - editor.tasks.setVisible(!editor.tasks.isVisible()); - } - else - { - editor.showTasks(); - } - }); - - this.addAction('toggleHelp', function(editor) - { - if (editor.help != null) - { - editor.help.setVisible(!editor.help.isVisible()); - } - else - { - editor.showHelp(); - } - }); - - this.addAction('toggleOutline', function(editor) - { - if (editor.outline == null) - { - editor.showOutline(); - } - else - { - editor.outline.setVisible(!editor.outline.isVisible()); - } - }); - - this.addAction('toggleConsole', function(editor) - { - mxLog.setVisible(!mxLog.isVisible()); - }); -}; - -/** - * Function: createSession - * - * Creates and returns and <mxSession> using <urlInit>, <urlPoll> and <urlNotify>. - */ -mxEditor.prototype.createSession = function () -{ - // Routes any change events from the session - // through the editor and dispatches them as - // a session event. - var sessionChanged = mxUtils.bind(this, function(session) - { - this.fireEvent(new mxEventObject(mxEvent.SESSION, 'session', session)); - }); - - return this.connect(this.urlInit, this.urlPoll, - this.urlNotify, sessionChanged); -}; - -/** - * Function: configure - * - * Configures the editor using the specified node. To load the - * configuration from a given URL the following code can be used to obtain - * the XML node. - * - * (code) - * var node = mxUtils.load(url).getDocumentElement(); - * (end) - * - * Parameters: - * - * node - XML node that contains the configuration. - */ -mxEditor.prototype.configure = function (node) -{ - if (node != null) - { - // Creates a decoder for the XML data - // and uses it to configure the editor - var dec = new mxCodec(node.ownerDocument); - dec.decode(node, this); - - // Resets the counters, modified state and - // command history - this.resetHistory(); - } -}; - -/** - * Function: resetFirstTime - * - * Resets the cookie that is used to remember if the editor has already - * been used. - */ -mxEditor.prototype.resetFirstTime = function () -{ - document.cookie = - 'mxgraph=seen; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/'; -}; - -/** - * Function: resetHistory - * - * Resets the command history, modified state and counters. - */ -mxEditor.prototype.resetHistory = function () -{ - this.lastSnapshot = new Date().getTime(); - this.undoManager.clear(); - this.ignoredChanges = 0; - this.setModified(false); -}; - -/** - * Function: addAction - * - * Binds the specified actionname to the specified function. - * - * Parameters: - * - * actionname - String that specifies the name of the action - * to be added. - * funct - Function that implements the new action. The first - * argument of the function is the editor it is used - * with, the second argument is the cell it operates - * upon. - * - * Example: - * (code) - * editor.addAction('test', function(editor, cell) - * { - * mxUtils.alert("test "+cell); - * }); - * (end) - */ -mxEditor.prototype.addAction = function (actionname, funct) -{ - this.actions[actionname] = funct; -}; - -/** - * Function: execute - * - * Executes the function with the given name in <actions> passing the - * editor instance and given cell as the first and second argument. All - * additional arguments are passed to the action as well. This method - * contains a try-catch block and displays an error message if an action - * causes an exception. The exception is re-thrown after the error - * message was displayed. - * - * Example: - * - * (code) - * editor.execute("showProperties", cell); - * (end) - */ -mxEditor.prototype.execute = function (actionname, cell, evt) -{ - var action = this.actions[actionname]; - - if (action != null) - { - try - { - // Creates the array of arguments by replacing the actionname - // with the editor instance in the args of this function - var args = arguments; - args[0] = this; - - // Invokes the function on the editor using the args - action.apply(this, args); - } - catch (e) - { - mxUtils.error('Cannot execute ' + actionname + - ': ' + e.message, 280, true); - - throw e; - } - } - else - { - mxUtils.error('Cannot find action '+actionname, 280, true); - } -}; - -/** - * Function: addTemplate - * - * Adds the specified template under the given name in <templates>. - */ -mxEditor.prototype.addTemplate = function (name, template) -{ - this.templates[name] = template; -}; - -/** - * Function: getTemplate - * - * Returns the template for the given name. - */ -mxEditor.prototype.getTemplate = function (name) -{ - return this.templates[name]; -}; - -/** - * Function: createGraph - * - * Creates the <graph> for the editor. The graph is created with no - * container and is initialized from <setGraphContainer>. - */ -mxEditor.prototype.createGraph = function () -{ - var graph = new mxGraph(null, null, this.graphRenderHint); - - // Enables rubberband, tooltips, panning - graph.setTooltips(true); - graph.setPanning(true); - - // Overrides the dblclick method on the graph to - // invoke the dblClickAction for a cell and reset - // the selection tool in the toolbar - this.installDblClickHandler(graph); - - // Installs the command history - this.installUndoHandler(graph); - - // Installs the handlers for the root event - this.installDrillHandler(graph); - - // Installs the handler for validation - this.installChangeHandler(graph); - - // Installs the handler for calling the - // insert function and consume the - // event if an insert function is defined - this.installInsertHandler(graph); - - // Redirects the function for creating the - // popupmenu items - graph.panningHandler.factoryMethod = - mxUtils.bind(this, function(menu, cell, evt) - { - return this.createPopupMenu(menu, cell, evt); - }); - - // Redirects the function for creating - // new connections in the diagram - graph.connectionHandler.factoryMethod = - mxUtils.bind(this, function(source, target) - { - return this.createEdge(source, target); - }); - - // Maintains swimlanes and installs autolayout - this.createSwimlaneManager(graph); - this.createLayoutManager(graph); - - return graph; -}; - -/** - * Function: createSwimlaneManager - * - * Sets the graph's container using <mxGraph.init>. - */ -mxEditor.prototype.createSwimlaneManager = function (graph) -{ - var swimlaneMgr = new mxSwimlaneManager(graph, false); - - swimlaneMgr.isHorizontal = mxUtils.bind(this, function() - { - return this.horizontalFlow; - }); - - swimlaneMgr.isEnabled = mxUtils.bind(this, function() - { - return this.maintainSwimlanes; - }); - - return swimlaneMgr; -}; - -/** - * Function: createLayoutManager - * - * Creates a layout manager for the swimlane and diagram layouts, that - * is, the locally defined inter- and intraswimlane layouts. - */ -mxEditor.prototype.createLayoutManager = function (graph) -{ - var layoutMgr = new mxLayoutManager(graph); - - var self = this; // closure - layoutMgr.getLayout = function(cell) - { - var layout = null; - var model = self.graph.getModel(); - - if (model.getParent(cell) != null) - { - // Executes the swimlane layout if a child of - // a swimlane has been changed. The layout is - // lazy created in createSwimlaneLayout. - if (self.layoutSwimlanes && - graph.isSwimlane(cell)) - { - if (self.swimlaneLayout == null) - { - self.swimlaneLayout = self.createSwimlaneLayout(); - } - - layout = self.swimlaneLayout; - } - - // Executes the diagram layout if the modified - // cell is a top-level cell. The layout is - // lazy created in createDiagramLayout. - else if (self.layoutDiagram && - (graph.isValidRoot(cell) || - model.getParent(model.getParent(cell)) == null)) - { - if (self.diagramLayout == null) - { - self.diagramLayout = self.createDiagramLayout(); - } - - layout = self.diagramLayout; - } - } - - return layout; - }; - - return layoutMgr; -}; - -/** - * Function: setGraphContainer - * - * Sets the graph's container using <mxGraph.init>. - */ -mxEditor.prototype.setGraphContainer = function (container) -{ - if (this.graph.container == null) - { - // Creates the graph instance inside the given container and render hint - //this.graph = new mxGraph(container, null, this.graphRenderHint); - this.graph.init(container); - - // Install rubberband selection as the last - // action handler in the chain - this.rubberband = new mxRubberband(this.graph); - - // Disables the context menu - if (this.disableContextMenu) - { - mxEvent.disableContextMenu(container); - } - - // Workaround for stylesheet directives in IE - if (mxClient.IS_QUIRKS) - { - new mxDivResizer(container); - } - } -}; - -/** - * Function: installDblClickHandler - * - * Overrides <mxGraph.dblClick> to invoke <dblClickAction> - * on a cell and reset the selection tool in the toolbar. - */ -mxEditor.prototype.installDblClickHandler = function (graph) -{ - // Installs a listener for double click events - graph.addListener(mxEvent.DOUBLE_CLICK, - mxUtils.bind(this, function(sender, evt) - { - var cell = evt.getProperty('cell'); - - if (cell != null && - graph.isEnabled() && - this.dblClickAction != null) - { - this.execute(this.dblClickAction, cell); - evt.consume(); - } - }) - ); -}; - -/** - * Function: installUndoHandler - * - * Adds the <undoManager> to the graph model and the view. - */ -mxEditor.prototype.installUndoHandler = function (graph) -{ - var listener = mxUtils.bind(this, function(sender, evt) - { - var edit = evt.getProperty('edit'); - this.undoManager.undoableEditHappened(edit); - }); - - graph.getModel().addListener(mxEvent.UNDO, listener); - graph.getView().addListener(mxEvent.UNDO, listener); - - // Keeps the selection state in sync - var undoHandler = function(sender, evt) - { - var changes = evt.getProperty('edit').changes; - graph.setSelectionCells(graph.getSelectionCellsForChanges(changes)); - }; - - this.undoManager.addListener(mxEvent.UNDO, undoHandler); - this.undoManager.addListener(mxEvent.REDO, undoHandler); -}; - -/** - * Function: installDrillHandler - * - * Installs listeners for dispatching the <root> event. - */ -mxEditor.prototype.installDrillHandler = function (graph) -{ - var listener = mxUtils.bind(this, function(sender) - { - this.fireEvent(new mxEventObject(mxEvent.ROOT)); - }); - - graph.getView().addListener(mxEvent.DOWN, listener); - graph.getView().addListener(mxEvent.UP, listener); -}; - -/** - * Function: installChangeHandler - * - * Installs the listeners required to automatically validate - * the graph. On each change of the root, this implementation - * fires a <root> event. - */ -mxEditor.prototype.installChangeHandler = function (graph) -{ - var listener = mxUtils.bind(this, function(sender, evt) - { - // Updates the modified state - this.setModified(true); - - // Automatically validates the graph - // after each change - if (this.validating == true) - { - graph.validateGraph(); - } - - // Checks if the root has been changed - var changes = evt.getProperty('edit').changes; - - for (var i = 0; i < changes.length; i++) - { - var change = changes[i]; - - if (change instanceof mxRootChange || - (change instanceof mxValueChange && - change.cell == this.graph.model.root) || - (change instanceof mxCellAttributeChange && - change.cell == this.graph.model.root)) - { - this.fireEvent(new mxEventObject(mxEvent.ROOT)); - break; - } - } - }); - - graph.getModel().addListener(mxEvent.CHANGE, listener); -}; - -/** - * Function: installInsertHandler - * - * Installs the handler for invoking <insertFunction> if - * one is defined. - */ -mxEditor.prototype.installInsertHandler = function (graph) -{ - var self = this; // closure - var insertHandler = - { - mouseDown: function(sender, me) - { - if (self.insertFunction != null && - !me.isPopupTrigger() && - (self.forcedInserting || - me.getState() == null)) - { - self.graph.clearSelection(); - self.insertFunction(me.getEvent(), me.getCell()); - - // Consumes the rest of the events - // for this gesture (down, move, up) - this.isActive = true; - me.consume(); - } - }, - - mouseMove: function(sender, me) - { - if (this.isActive) - { - me.consume(); - } - }, - - mouseUp: function(sender, me) - { - if (this.isActive) - { - this.isActive = false; - me.consume(); - } - } - }; - - graph.addMouseListener(insertHandler); -}; - -/** - * Function: createDiagramLayout - * - * Creates the layout instance used to layout the - * swimlanes in the diagram. - */ -mxEditor.prototype.createDiagramLayout = function () -{ - var gs = this.graph.gridSize; - var layout = new mxStackLayout(this.graph, !this.horizontalFlow, - this.swimlaneSpacing, 2*gs, 2*gs); - - // Overrides isIgnored to only take into account swimlanes - layout.isVertexIgnored = function(cell) - { - return !layout.graph.isSwimlane(cell); - }; - - return layout; -}; - -/** - * Function: createSwimlaneLayout - * - * Creates the layout instance used to layout the - * children of each swimlane. - */ -mxEditor.prototype.createSwimlaneLayout = function () -{ - return new mxCompactTreeLayout(this.graph, this.horizontalFlow); -}; - -/** - * Function: createToolbar - * - * Creates the <toolbar> with no container. - */ -mxEditor.prototype.createToolbar = function () -{ - return new mxDefaultToolbar(null, this); -}; - -/** - * Function: setToolbarContainer - * - * Initializes the toolbar for the given container. - */ -mxEditor.prototype.setToolbarContainer = function (container) -{ - this.toolbar.init(container); - - // Workaround for stylesheet directives in IE - if (mxClient.IS_QUIRKS) - { - new mxDivResizer(container); - } -}; - -/** - * Function: setStatusContainer - * - * Creates the <status> using the specified container. - * - * This implementation adds listeners in the editor to - * display the last saved time and the current filename - * in the status bar. - * - * Parameters: - * - * container - DOM node that will contain the statusbar. - */ -mxEditor.prototype.setStatusContainer = function (container) -{ - if (this.status == null) - { - this.status = container; - - // Prints the last saved time in the status bar - // when files are saved - this.addListener(mxEvent.SAVE, mxUtils.bind(this, function() - { - var tstamp = new Date().toLocaleString(); - this.setStatus((mxResources.get(this.lastSavedResource) || - this.lastSavedResource)+': '+tstamp); - })); - - // Updates the statusbar to display the filename - // when new files are opened - this.addListener(mxEvent.OPEN, mxUtils.bind(this, function() - { - this.setStatus((mxResources.get(this.currentFileResource) || - this.currentFileResource)+': '+this.filename); - })); - - // Workaround for stylesheet directives in IE - if (mxClient.IS_QUIRKS) - { - new mxDivResizer(container); - } - } -}; - -/** - * Function: setStatus - * - * Display the specified message in the status bar. - * - * Parameters: - * - * message - String the specified the message to - * be displayed. - */ -mxEditor.prototype.setStatus = function (message) -{ - if (this.status != null && message != null) - { - this.status.innerHTML = message; - } -}; - -/** - * Function: setTitleContainer - * - * Creates a listener to update the inner HTML of the - * specified DOM node with the value of <getTitle>. - * - * Parameters: - * - * container - DOM node that will contain the title. - */ -mxEditor.prototype.setTitleContainer = function (container) -{ - this.addListener(mxEvent.ROOT, mxUtils.bind(this, function(sender) - { - container.innerHTML = this.getTitle(); - })); - - // Workaround for stylesheet directives in IE - if (mxClient.IS_QUIRKS) - { - new mxDivResizer(container); - } -}; - -/** - * Function: treeLayout - * - * Executes a vertical or horizontal compact tree layout - * using the specified cell as an argument. The cell may - * either be a group or the root of a tree. - * - * Parameters: - * - * cell - <mxCell> to use in the compact tree layout. - * horizontal - Optional boolean to specify the tree's - * orientation. Default is true. - */ -mxEditor.prototype.treeLayout = function (cell, horizontal) -{ - if (cell != null) - { - var layout = new mxCompactTreeLayout(this.graph, horizontal); - layout.execute(cell); - } -}; - -/** - * Function: getTitle - * - * Returns the string value for the current root of the - * diagram. - */ -mxEditor.prototype.getTitle = function () -{ - var title = ''; - var graph = this.graph; - var cell = graph.getCurrentRoot(); - - while (cell != null && - graph.getModel().getParent( - graph.getModel().getParent(cell)) != null) - { - // Append each label of a valid root - if (graph.isValidRoot(cell)) - { - title = ' > ' + - graph.convertValueToString(cell) + title; - } - - cell = graph.getModel().getParent(cell); - } - - var prefix = this.getRootTitle(); - - return prefix + title; -}; - -/** - * Function: getRootTitle - * - * Returns the string value of the root cell in - * <mxGraph.model>. - */ -mxEditor.prototype.getRootTitle = function () -{ - var root = this.graph.getModel().getRoot(); - return this.graph.convertValueToString(root); -}; - -/** - * Function: undo - * - * Undo the last change in <graph>. - */ -mxEditor.prototype.undo = function () -{ - this.undoManager.undo(); -}; - -/** - * Function: redo - * - * Redo the last change in <graph>. - */ -mxEditor.prototype.redo = function () -{ - this.undoManager.redo(); -}; - -/** - * Function: groupCells - * - * Invokes <createGroup> to create a new group cell and the invokes - * <mxGraph.groupCells>, using the grid size of the graph as the spacing - * in the group's content area. - */ -mxEditor.prototype.groupCells = function () -{ - var border = (this.groupBorderSize != null) ? - this.groupBorderSize : - this.graph.gridSize; - return this.graph.groupCells(this.createGroup(), border); -}; - -/** - * Function: createGroup - * - * Creates and returns a clone of <defaultGroup> to be used - * as a new group cell in <group>. - */ -mxEditor.prototype.createGroup = function () -{ - var model = this.graph.getModel(); - - return model.cloneCell(this.defaultGroup); -}; - -/** - * Function: open - * - * Opens the specified file synchronously and parses it using - * <readGraphModel>. It updates <filename> and fires an <open>-event after - * the file has been opened. Exceptions should be handled as follows: - * - * (code) - * try - * { - * editor.open(filename); - * } - * catch (e) - * { - * mxUtils.error('Cannot open ' + filename + - * ': ' + e.message, 280, true); - * } - * (end) - * - * Parameters: - * - * filename - URL of the file to be opened. - */ -mxEditor.prototype.open = function (filename) -{ - if (filename != null) - { - var xml = mxUtils.load(filename).getXml(); - this.readGraphModel(xml.documentElement); - this.filename = filename; - - this.fireEvent(new mxEventObject(mxEvent.OPEN, 'filename', filename)); - } -}; - -/** - * Function: readGraphModel - * - * Reads the specified XML node into the existing graph model and resets - * the command history and modified state. - */ -mxEditor.prototype.readGraphModel = function (node) -{ - var dec = new mxCodec(node.ownerDocument); - dec.decode(node, this.graph.getModel()); - this.resetHistory(); -}; - -/** - * Function: save - * - * Posts the string returned by <writeGraphModel> to the given URL or the - * URL returned by <getUrlPost>. The actual posting is carried out by - * <postDiagram>. If the URL is null then the resulting XML will be - * displayed using <mxUtils.popup>. Exceptions should be handled as - * follows: - * - * (code) - * try - * { - * editor.save(); - * } - * catch (e) - * { - * mxUtils.error('Cannot save : ' + e.message, 280, true); - * } - * (end) - */ -mxEditor.prototype.save = function (url, linefeed) -{ - // Gets the URL to post the data to - url = url || this.getUrlPost(); - - // Posts the data if the URL is not empty - if (url != null && url.length > 0) - { - var data = this.writeGraphModel(linefeed); - this.postDiagram(url, data); - - // Resets the modified flag - this.setModified(false); - } - - // Dispatches a save event - this.fireEvent(new mxEventObject(mxEvent.SAVE, 'url', url)); -}; - -/** - * Function: postDiagram - * - * Hook for subclassers to override the posting of a diagram - * represented by the given node to the given URL. This fires - * an asynchronous <post> event if the diagram has been posted. - * - * Example: - * - * To replace the diagram with the diagram in the response, use the - * following code. - * - * (code) - * editor.addListener(mxEvent.POST, function(sender, evt) - * { - * // Process response (replace diagram) - * var req = evt.getProperty('request'); - * var root = req.getDocumentElement(); - * editor.graph.readGraphModel(root) - * }); - * (end) - */ -mxEditor.prototype.postDiagram = function (url, data) -{ - if (this.escapePostData) - { - data = encodeURIComponent(data); - } - - mxUtils.post(url, this.postParameterName+'='+data, - mxUtils.bind(this, function(req) - { - this.fireEvent(new mxEventObject(mxEvent.POST, - 'request', req, 'url', url, 'data', data)); - }) - ); -}; - -/** - * Function: writeGraphModel - * - * Hook to create the string representation of the diagram. The default - * implementation uses an <mxCodec> to encode the graph model as - * follows: - * - * (code) - * var enc = new mxCodec(); - * var node = enc.encode(this.graph.getModel()); - * return mxUtils.getXml(node, this.linefeed); - * (end) - * - * Parameters: - * - * linefeed - Optional character to be used as the linefeed. Default is - * <linefeed>. - */ -mxEditor.prototype.writeGraphModel = function (linefeed) -{ - linefeed = (linefeed != null) ? linefeed : this.linefeed; - var enc = new mxCodec(); - var node = enc.encode(this.graph.getModel()); - - return mxUtils.getXml(node, linefeed); -}; - -/** - * Function: getUrlPost - * - * Returns the URL to post the diagram to. This is used - * in <save>. The default implementation returns <urlPost>, - * adding <code>?draft=true</code>. - */ -mxEditor.prototype.getUrlPost = function () -{ - return this.urlPost; -}; - -/** - * Function: getUrlImage - * - * Returns the URL to create the image with. This is typically - * the URL of a backend which accepts an XML representation - * of a graph view to create an image. The function is used - * in the image action to create an image. This implementation - * returns <urlImage>. - */ -mxEditor.prototype.getUrlImage = function () -{ - return this.urlImage; -}; - -/** - * Function: connect - * - * Creates and returns a session for the specified parameters, installing - * the onChange function as a change listener for the session. - */ -mxEditor.prototype.connect = function (urlInit, urlPoll, urlNotify, onChange) -{ - var session = null; - - if (!mxClient.IS_LOCAL) - { - session = new mxSession(this.graph.getModel(), - urlInit, urlPoll, urlNotify); - - // Resets the undo history if the session was initialized which is the - // case if the message carries a namespace to be used for new IDs. - session.addListener(mxEvent.RECEIVE, - mxUtils.bind(this, function(sender, evt) - { - var node = evt.getProperty('node'); - - if (node.getAttribute('namespace') != null) - { - this.resetHistory(); - } - }) - ); - - // Installs the listener for all events - // that signal a change of the session - session.addListener(mxEvent.DISCONNECT, onChange); - session.addListener(mxEvent.CONNECT, onChange); - session.addListener(mxEvent.NOTIFY, onChange); - session.addListener(mxEvent.GET, onChange); - session.start(); - } - - return session; -}; - -/** - * Function: swapStyles - * - * Swaps the styles for the given names in the graph's - * stylesheet and refreshes the graph. - */ -mxEditor.prototype.swapStyles = function (first, second) -{ - var style = this.graph.getStylesheet().styles[second]; - this.graph.getView().getStylesheet().putCellStyle( - second, this.graph.getStylesheet().styles[first]); - this.graph.getStylesheet().putCellStyle(first, style); - this.graph.refresh(); -}; - -/** - * Function: showProperties - * - * Creates and shows the properties dialog for the given - * cell. The content area of the dialog is created using - * <createProperties>. - */ -mxEditor.prototype.showProperties = function (cell) -{ - cell = cell || this.graph.getSelectionCell(); - - // Uses the root node for the properties dialog - // if not cell was passed in and no cell is - // selected - if (cell == null) - { - cell = this.graph.getCurrentRoot(); - - if (cell == null) - { - cell = this.graph.getModel().getRoot(); - } - } - - if (cell != null) - { - // Makes sure there is no in-place editor in the - // graph and computes the location of the dialog - this.graph.stopEditing(true); - - var offset = mxUtils.getOffset(this.graph.container); - var x = offset.x+10; - var y = offset.y; - - // Avoids moving the dialog if it is alredy open - if (this.properties != null && !this.movePropertiesDialog) - { - x = this.properties.getX(); - y = this.properties.getY(); - } - - // Places the dialog near the cell for which it - // displays the properties - else - { - var bounds = this.graph.getCellBounds(cell); - - if (bounds != null) - { - x += bounds.x+Math.min(200, bounds.width); - y += bounds.y; - } - } - - // Hides the existing properties dialog and creates a new one with the - // contents created in the hook method - this.hideProperties(); - var node = this.createProperties(cell); - - if (node != null) - { - // Displays the contents in a window and stores a reference to the - // window for later hiding of the window - this.properties = new mxWindow(mxResources.get(this.propertiesResource) || - this.propertiesResource, node, x, y, this.propertiesWidth, this.propertiesHeight, false); - this.properties.setVisible(true); - } - } -}; - -/** - * Function: isPropertiesVisible - * - * Returns true if the properties dialog is currently visible. - */ -mxEditor.prototype.isPropertiesVisible = function () -{ - return this.properties != null; -}; - -/** - * Function: createProperties - * - * Creates and returns the DOM node that represents the contents - * of the properties dialog for the given cell. This implementation - * works for user objects that are XML nodes and display all the - * node attributes in a form. - */ -mxEditor.prototype.createProperties = function (cell) -{ - var model = this.graph.getModel(); - var value = model.getValue(cell); - - if (mxUtils.isNode(value)) - { - // Creates a form for the user object inside - // the cell - var form = new mxForm('properties'); - - // Adds a readonly field for the cell id - var id = form.addText('ID', cell.getId()); - id.setAttribute('readonly', 'true'); - - var geo = null; - var yField = null; - var xField = null; - var widthField = null; - var heightField = null; - - // Adds fields for the location and size - if (model.isVertex(cell)) - { - geo = model.getGeometry(cell); - - if (geo != null) - { - yField = form.addText('top', geo.y); - xField = form.addText('left', geo.x); - widthField = form.addText('width', geo.width); - heightField = form.addText('height', geo.height); - } - } - - // Adds a field for the cell style - var tmp = model.getStyle(cell); - var style = form.addText('Style', tmp || ''); - - // Creates textareas for each attribute of the - // user object within the cell - var attrs = value.attributes; - var texts = []; - - for (var i = 0; i < attrs.length; i++) - { - // Creates a textarea with more lines for - // the cell label - var val = attrs[i].nodeValue; - texts[i] = form.addTextarea(attrs[i].nodeName, val, - (attrs[i].nodeName == 'label') ? 4 : 2); - } - - // Adds an OK and Cancel button to the dialog - // contents and implements the respective - // actions below - - // Defines the function to be executed when the - // OK button is pressed in the dialog - var okFunction = mxUtils.bind(this, function() - { - // Hides the dialog - this.hideProperties(); - - // Supports undo for the changes on the underlying - // XML structure / XML node attribute changes. - model.beginUpdate(); - try - { - if (geo != null) - { - geo = geo.clone(); - - geo.x = parseFloat(xField.value); - geo.y = parseFloat(yField.value); - geo.width = parseFloat(widthField.value); - geo.height = parseFloat(heightField.value); - - model.setGeometry(cell, geo); - } - - // Applies the style - if (style.value.length > 0) - { - model.setStyle(cell, style.value); - } - else - { - model.setStyle(cell, null); - } - - // Creates an undoable change for each - // attribute and executes it using the - // model, which will also make the change - // part of the current transaction - for (var i=0; i<attrs.length; i++) - { - var edit = new mxCellAttributeChange( - cell, attrs[i].nodeName, - texts[i].value); - model.execute(edit); - } - - // Checks if the graph wants cells to - // be automatically sized and updates - // the size as an undoable step if - // the feature is enabled - if (this.graph.isAutoSizeCell(cell)) - { - this.graph.updateCellSize(cell); - } - } - finally - { - model.endUpdate(); - } - }); - - // Defines the function to be executed when the - // Cancel button is pressed in the dialog - var cancelFunction = mxUtils.bind(this, function() - { - // Hides the dialog - this.hideProperties(); - }); - - form.addButtons(okFunction, cancelFunction); - - return form.table; - } - - return null; -}; - -/** - * Function: hideProperties - * - * Hides the properties dialog. - */ -mxEditor.prototype.hideProperties = function () -{ - if (this.properties != null) - { - this.properties.destroy(); - this.properties = null; - } -}; - -/** - * Function: showTasks - * - * Shows the tasks window. The tasks window is created using <createTasks>. The - * default width of the window is 200 pixels, the y-coordinate of the location - * can be specifies in <tasksTop> and the x-coordinate is right aligned with a - * 20 pixel offset from the right border. To change the location of the tasks - * window, the following code can be used: - * - * (code) - * var oldShowTasks = mxEditor.prototype.showTasks; - * mxEditor.prototype.showTasks = function() - * { - * oldShowTasks.apply(this, arguments); // "supercall" - * - * if (this.tasks != null) - * { - * this.tasks.setLocation(10, 10); - * } - * }; - * (end) - */ -mxEditor.prototype.showTasks = function () -{ - if (this.tasks == null) - { - var div = document.createElement('div'); - div.style.padding = '4px'; - div.style.paddingLeft = '20px'; - var w = document.body.clientWidth; - var wnd = new mxWindow( - mxResources.get(this.tasksResource) || - this.tasksResource, - div, w - 220, this.tasksTop, 200); - wnd.setClosable(true); - wnd.destroyOnClose = false; - - // Installs a function to update the contents - // of the tasks window on every change of the - // model, selection or root. - var funct = mxUtils.bind(this, function(sender) - { - mxEvent.release(div); - div.innerHTML = ''; - this.createTasks(div); - }); - - this.graph.getModel().addListener(mxEvent.CHANGE, funct); - this.graph.getSelectionModel().addListener(mxEvent.CHANGE, funct); - this.graph.addListener(mxEvent.ROOT, funct); - - // Assigns the icon to the tasks window - if (this.tasksWindowImage != null) - { - wnd.setImage(this.tasksWindowImage); - } - - this.tasks = wnd; - this.createTasks(div); - } - - this.tasks.setVisible(true); -}; - -/** - * Function: refreshTasks - * - * Updates the contents of the tasks window using <createTasks>. - */ -mxEditor.prototype.refreshTasks = function (div) -{ - if (this.tasks != null) - { - var div = this.tasks.content; - mxEvent.release(div); - div.innerHTML = ''; - this.createTasks(div); - } -}; - -/** - * Function: createTasks - * - * Updates the contents of the given DOM node to - * display the tasks associated with the current - * editor state. This is invoked whenever there - * is a possible change of state in the editor. - * Default implementation is empty. - */ -mxEditor.prototype.createTasks = function (div) -{ - // override -}; - -/** - * Function: showHelp - * - * Shows the help window. If the help window does not exist - * then it is created using an iframe pointing to the resource - * for the <code>urlHelp</code> key or <urlHelp> if the resource - * is undefined. - */ -mxEditor.prototype.showHelp = function (tasks) -{ - if (this.help == null) - { - var frame = document.createElement('iframe'); - frame.setAttribute('src', mxResources.get('urlHelp') || this.urlHelp); - frame.setAttribute('height', '100%'); - frame.setAttribute('width', '100%'); - frame.setAttribute('frameBorder', '0'); - frame.style.backgroundColor = 'white'; - - var w = document.body.clientWidth; - var h = (document.body.clientHeight || document.documentElement.clientHeight); - - var wnd = new mxWindow(mxResources.get(this.helpResource) || this.helpResource, - frame, (w-this.helpWidth)/2, (h-this.helpHeight)/3, this.helpWidth, this.helpHeight); - wnd.setMaximizable(true); - wnd.setClosable(true); - wnd.destroyOnClose = false; - wnd.setResizable(true); - - // Assigns the icon to the help window - if (this.helpWindowImage != null) - { - wnd.setImage(this.helpWindowImage); - } - - // Workaround for ignored iframe height 100% in FF - if (mxClient.IS_NS) - { - var handler = function(sender) - { - var h = wnd.div.offsetHeight; - frame.setAttribute('height', (h-26)+'px'); - }; - - wnd.addListener(mxEvent.RESIZE_END, handler); - wnd.addListener(mxEvent.MAXIMIZE, handler); - wnd.addListener(mxEvent.NORMALIZE, handler); - wnd.addListener(mxEvent.SHOW, handler); - } - - this.help = wnd; - } - - this.help.setVisible(true); -}; - -/** - * Function: showOutline - * - * Shows the outline window. If the window does not exist, then it is - * created using an <mxOutline>. - */ -mxEditor.prototype.showOutline = function () -{ - var create = this.outline == null; - - if (create) - { - var div = document.createElement('div'); - div.style.overflow = 'hidden'; - div.style.width = '100%'; - div.style.height = '100%'; - div.style.background = 'white'; - div.style.cursor = 'move'; - - var wnd = new mxWindow( - mxResources.get(this.outlineResource) || - this.outlineResource, - div, 600, 480, 200, 200, false); - - // Creates the outline in the specified div - // and links it to the existing graph - var outline = new mxOutline(this.graph, div); - wnd.setClosable(true); - wnd.setResizable(true); - wnd.destroyOnClose = false; - - wnd.addListener(mxEvent.RESIZE_END, function() - { - outline.update(); - }); - - this.outline = wnd; - this.outline.outline = outline; - } - - // Finally shows the outline - this.outline.setVisible(true); - this.outline.outline.update(true); -}; - -/** - * Function: setMode - * - * Puts the graph into the specified mode. The following modenames are - * supported: - * - * select - Selects using the left mouse button, new connections - * are disabled. - * connect - Selects using the left mouse button or creates new - * connections if mouse over cell hotspot. See <mxConnectionHandler>. - * pan - Pans using the left mouse button, new connections are disabled. - */ -mxEditor.prototype.setMode = function(modename) -{ - if (modename == 'select') - { - this.graph.panningHandler.useLeftButtonForPanning = false; - this.graph.setConnectable(false); - } - else if (modename == 'connect') - { - this.graph.panningHandler.useLeftButtonForPanning = false; - this.graph.setConnectable(true); - } - else if (modename == 'pan') - { - this.graph.panningHandler.useLeftButtonForPanning = true; - this.graph.setConnectable(false); - } -}; - -/** - * Function: createPopupMenu - * - * Uses <popupHandler> to create the menu in the graph's - * panning handler. The redirection is setup in - * <setToolbarContainer>. - */ -mxEditor.prototype.createPopupMenu = function (menu, cell, evt) -{ - this.popupHandler.createMenu(this, menu, cell, evt); -}; - -/** - * Function: createEdge - * - * Uses <defaultEdge> as the prototype for creating new edges - * in the connection handler of the graph. The style of the - * edge will be overridden with the value returned by - * <getEdgeStyle>. - */ -mxEditor.prototype.createEdge = function (source, target) -{ - // Clones the defaultedge prototype - var e = null; - - if (this.defaultEdge != null) - { - var model = this.graph.getModel(); - e = model.cloneCell(this.defaultEdge); - } - else - { - e = new mxCell(''); - e.setEdge(true); - - var geo = new mxGeometry(); - geo.relative = true; - e.setGeometry(geo); - } - - // Overrides the edge style - var style = this.getEdgeStyle(); - - if (style != null) - { - e.setStyle(style); - } - - return e; -}; - -/** - * Function: getEdgeStyle - * - * Returns a string identifying the style of new edges. - * The function is used in <createEdge> when new edges - * are created in the graph. - */ -mxEditor.prototype.getEdgeStyle = function () -{ - return this.defaultEdgeStyle; -}; - -/** - * Function: consumeCycleAttribute - * - * Returns the next attribute in <cycleAttributeValues> - * or null, if not attribute should be used in the - * specified cell. - */ -mxEditor.prototype.consumeCycleAttribute = function (cell) -{ - return (this.cycleAttributeValues != null && - this.cycleAttributeValues.length > 0 && - this.graph.isSwimlane(cell)) ? - this.cycleAttributeValues[this.cycleAttributeIndex++ % - this.cycleAttributeValues.length] : null; -}; - -/** - * Function: cycleAttribute - * - * Uses the returned value from <consumeCycleAttribute> - * as the value for the <cycleAttributeName> key in - * the given cell's style. - */ -mxEditor.prototype.cycleAttribute = function (cell) -{ - if (this.cycleAttributeName != null) - { - var value = this.consumeCycleAttribute(cell); - - if (value != null) - { - cell.setStyle(cell.getStyle()+';'+ - this.cycleAttributeName+'='+value); - } - } -}; - -/** - * Function: addVertex - * - * Adds the given vertex as a child of parent at the specified - * x and y coordinate and fires an <addVertex> event. - */ -mxEditor.prototype.addVertex = function (parent, vertex, x, y) -{ - var model = this.graph.getModel(); - - while (parent != null && !this.graph.isValidDropTarget(parent)) - { - parent = model.getParent(parent); - } - - parent = (parent != null) ? parent : this.graph.getSwimlaneAt(x, y); - var scale = this.graph.getView().scale; - - var geo = model.getGeometry(vertex); - var pgeo = model.getGeometry(parent); - - if (this.graph.isSwimlane(vertex) && - !this.graph.swimlaneNesting) - { - parent = null; - } - else if (parent == null && this.swimlaneRequired) - { - return null; - } - else if (parent != null && pgeo != null) - { - // Keeps vertex inside parent - var state = this.graph.getView().getState(parent); - - if (state != null) - { - x -= state.origin.x * scale; - y -= state.origin.y * scale; - - if (this.graph.isConstrainedMoving) - { - var width = geo.width; - var height = geo.height; - var tmp = state.x+state.width; - - if (x+width > tmp) - { - x -= x+width - tmp; - } - - tmp = state.y+state.height; - - if (y+height > tmp) - { - y -= y+height - tmp; - } - } - } - else if (pgeo != null) - { - x -= pgeo.x*scale; - y -= pgeo.y*scale; - } - } - - geo = geo.clone(); - geo.x = this.graph.snap(x / scale - - this.graph.getView().translate.x - - this.graph.gridSize/2); - geo.y = this.graph.snap(y / scale - - this.graph.getView().translate.y - - this.graph.gridSize/2); - vertex.setGeometry(geo); - - if (parent == null) - { - parent = this.graph.getDefaultParent(); - } - - this.cycleAttribute(vertex); - this.fireEvent(new mxEventObject(mxEvent.BEFORE_ADD_VERTEX, - 'vertex', vertex, 'parent', parent)); - - model.beginUpdate(); - try - { - vertex = this.graph.addCell(vertex, parent); - - if (vertex != null) - { - this.graph.constrainChild(vertex); - - this.fireEvent(new mxEventObject(mxEvent.ADD_VERTEX, 'vertex', vertex)); - } - } - finally - { - model.endUpdate(); - } - - if (vertex != null) - { - this.graph.setSelectionCell(vertex); - this.graph.scrollCellToVisible(vertex); - this.fireEvent(new mxEventObject(mxEvent.AFTER_ADD_VERTEX, 'vertex', vertex)); - } - - return vertex; -}; - -/** - * Function: destroy - * - * Removes the editor and all its associated resources. This does not - * normally need to be called, it is called automatically when the window - * unloads. - */ -mxEditor.prototype.destroy = function () -{ - if (!this.destroyed) - { - this.destroyed = true; - - if (this.tasks != null) - { - this.tasks.destroy(); - } - - if (this.outline != null) - { - this.outline.destroy(); - } - - if (this.properties != null) - { - this.properties.destroy(); - } - - if (this.keyHandler != null) - { - this.keyHandler.destroy(); - } - - if (this.rubberband != null) - { - this.rubberband.destroy(); - } - - if (this.toolbar != null) - { - this.toolbar.destroy(); - } - - if (this.graph != null) - { - this.graph.destroy(); - } - - this.status = null; - this.templates = null; - } -}; diff --git a/handler/mxKeyHandler.js b/handler/mxKeyHandler.js deleted file mode 100644 index cc07e51..0000000 --- a/handler/mxKeyHandler.js +++ /dev/null @@ -1,402 +0,0 @@ -/** - * $Id: mxKeyHandler.js,v 1.48 2012-03-30 08:30:41 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxKeyHandler - * - * Event handler that listens to keystroke events. This is not a singleton, - * however, it is normally only required once if the target is the document - * element (default). - * - * This handler installs a key event listener in the topmost DOM node and - * processes all events that originate from descandants of <mxGraph.container> - * or from the topmost DOM node. The latter means that all unhandled keystrokes - * are handled by this object regardless of the focused state of the <graph>. - * - * Example: - * - * The following example creates a key handler that listens to the delete key - * (46) and deletes the selection cells if the graph is enabled. - * - * (code) - * var keyHandler = new mxKeyHandler(graph); - * keyHandler.bindKey(46, function(evt) - * { - * if (graph.isEnabled()) - * { - * graph.removeCells(); - * } - * }); - * (end) - * - * Keycodes: - * - * See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of - * keycodes or install a key event listener into the document element and print - * the key codes of the respective events to the console. - * - * To support the Command key and the Control key on the Mac, the following - * code can be used. - * - * (code) - * keyHandler.getFunction = function(evt) - * { - * if (evt != null) - * { - * return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode]; - * } - * - * return null; - * }; - * (end) - * - * Constructor: mxKeyHandler - * - * Constructs an event handler that executes functions bound to specific - * keystrokes. - * - * Parameters: - * - * graph - Reference to the associated <mxGraph>. - * target - Optional reference to the event target. If null, the document - * element is used as the event target, that is, the object where the key - * event listener is installed. - */ -function mxKeyHandler(graph, target) -{ - if (graph != null) - { - this.graph = graph; - this.target = target || document.documentElement; - - // Creates the arrays to map from keycodes to functions - this.normalKeys = []; - this.shiftKeys = []; - this.controlKeys = []; - this.controlShiftKeys = []; - - // Installs the keystroke listener in the target - mxEvent.addListener(this.target, "keydown", - mxUtils.bind(this, function(evt) - { - this.keyDown(evt); - }) - ); - - // Automatically deallocates memory in IE - if (mxClient.IS_IE) - { - mxEvent.addListener(window, 'unload', - mxUtils.bind(this, function() - { - this.destroy(); - }) - ); - } - } -}; - -/** - * Variable: graph - * - * Reference to the <mxGraph> associated with this handler. - */ -mxKeyHandler.prototype.graph = null; - -/** - * Variable: target - * - * Reference to the target DOM, that is, the DOM node where the key event - * listeners are installed. - */ -mxKeyHandler.prototype.target = null; - -/** - * Variable: normalKeys - * - * Maps from keycodes to functions for non-pressed control keys. - */ -mxKeyHandler.prototype.normalKeys = null; - -/** - * Variable: shiftKeys - * - * Maps from keycodes to functions for pressed shift keys. - */ -mxKeyHandler.prototype.shiftKeys = null; - -/** - * Variable: controlKeys - * - * Maps from keycodes to functions for pressed control keys. - */ -mxKeyHandler.prototype.controlKeys = null; - -/** - * Variable: controlShiftKeys - * - * Maps from keycodes to functions for pressed control and shift keys. - */ -mxKeyHandler.prototype.controlShiftKeys = null; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxKeyHandler.prototype.enabled = true; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation returns - * <enabled>. - */ -mxKeyHandler.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Enables or disables event handling by updating <enabled>. - * - * Parameters: - * - * enabled - Boolean that specifies the new enabled state. - */ -mxKeyHandler.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: bindKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control key is not pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindKey = function(code, funct) -{ - this.normalKeys[code] = funct; -}; - -/** - * Function: bindShiftKey - * - * Binds the specified keycode to the given function. This binding is used - * if the shift key is pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindShiftKey = function(code, funct) -{ - this.shiftKeys[code] = funct; -}; - -/** - * Function: bindControlKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control key is pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindControlKey = function(code, funct) -{ - this.controlKeys[code] = funct; -}; - -/** - * Function: bindControlShiftKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control and shift key are pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindControlShiftKey = function(code, funct) -{ - this.controlShiftKeys[code] = funct; -}; - -/** - * Function: isControlDown - * - * Returns true if the control key is pressed. This uses <mxEvent.isControlDown>. - * - * Parameters: - * - * evt - Key event whose control key pressed state should be returned. - */ -mxKeyHandler.prototype.isControlDown = function(evt) -{ - return mxEvent.isControlDown(evt); -}; - -/** - * Function: getFunction - * - * Returns the function associated with the given key event or null if no - * function is associated with the given event. - * - * Parameters: - * - * evt - Key event whose associated function should be returned. - */ -mxKeyHandler.prototype.getFunction = function(evt) -{ - if (evt != null) - { - if (this.isControlDown(evt)) - { - if (mxEvent.isShiftDown(evt)) - { - return this.controlShiftKeys[evt.keyCode]; - } - else - { - return this.controlKeys[evt.keyCode]; - } - } - else - { - if (mxEvent.isShiftDown(evt)) - { - return this.shiftKeys[evt.keyCode]; - } - else - { - return this.normalKeys[evt.keyCode]; - } - } - } - - return null; -}; - -/** - * Function: isGraphEvent - * - * Returns true if the event should be processed by this handler, that is, - * if the event source is either the target, one of its direct children, a - * descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the - * <graph>. - * - * Parameters: - * - * evt - Key event that represents the keystroke. - */ -mxKeyHandler.prototype.isGraphEvent = function(evt) -{ - var source = mxEvent.getSource(evt); - - // Accepts events from the target object or - // in-place editing inside graph - if ((source == this.target || source.parentNode == this.target) || - (this.graph.cellEditor != null && source == this.graph.cellEditor.textarea)) - { - return true; - } - - // Accepts events from inside the container - var elt = source; - - while (elt != null) - { - if (elt == this.graph.container) - { - return true; - } - - elt = elt.parentNode; - } - - return false; -}; - -/** - * Function: keyDown - * - * Handles the event by invoking the function bound to the respective - * keystroke if <mxGraph.isEnabled>, <isEnabled> and <isGraphEvent> all - * return true for the given event and <mxGraph.isEditing> returns false. - * If the graph is editing only the <enter> and <escape> cases are handled - * by calling the respective hooks. - * - * Parameters: - * - * evt - Key event that represents the keystroke. - */ -mxKeyHandler.prototype.keyDown = function(evt) -{ - if (this.graph.isEnabled() && !mxEvent.isConsumed(evt) && - this.isGraphEvent(evt) && this.isEnabled()) - { - // Cancels the editing if escape is pressed - if (evt.keyCode == 27 /* Escape */) - { - this.escape(evt); - } - - // Invokes the function for the keystroke - else if (!this.graph.isEditing()) - { - var boundFunction = this.getFunction(evt); - - if (boundFunction != null) - { - boundFunction(evt); - mxEvent.consume(evt); - } - } - } -}; - -/** - * Function: escape - * - * Hook to process ESCAPE keystrokes. This implementation invokes - * <mxGraph.stopEditing> to cancel the current editing, connecting - * and/or other ongoing modifications. - * - * Parameters: - * - * evt - Key event that represents the keystroke. Possible keycode in this - * case is 27 (ESCAPE). - */ -mxKeyHandler.prototype.escape = function(evt) -{ - if (this.graph.isEscapeEnabled()) - { - this.graph.escape(evt); - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its references into the DOM. This does - * normally not need to be called, it is called automatically when the - * window unloads (in IE). - */ -mxKeyHandler.prototype.destroy = function() -{ - this.target = null; -}; @@ -8,8 +8,6 @@ <!-- Loads and initializes the library --> <script type="text/javascript" src="jquery/jquery-1.8.2.js"></script> <script type="text/javascript" src="mxClient.min.js"></script> - <script type="text/javascript" src="editor/mxDefaultKeyHandler.js"></script> - <script type="text/javascript" src="handler/mxKeyHandler.js"></script> <script type="text/javascript" src="jquery/farbtastic.js"></script> <link rel="stylesheet" href="jquery/farbtastic.css" type="text/css" /> @@ -17,7 +15,6 @@ <script type="text/javascript" src="details.js"></script> <script type="text/javascript" src="setup.js"></script> - <script type="text/javascript" src="json2.js"></script> <script type="text/javascript"> function main(container, outline, toolbar, sidebar, status) { // Checks if the browser is supported @@ -576,7 +573,7 @@ var enc = new mxCodec(mxUtils.createXmlDocument()); /*var array=[],key; for (key in diagRoot.model.cells) { - + if(diagRoot.model.cells[key].connectable == false) { array.push(diagRoot.model.cells[key].inst); @@ -590,7 +587,7 @@ textarea.value = str; /*var j = 0; for (key in diagRoot.model.cells) { - + if(diagRoot.model.cells[key].connectable == false) { diagRoot.model.cells[key].inst=array[j++]; diff --git a/json2.js b/json2.js deleted file mode 100644 index 5838457..0000000 --- a/json2.js +++ /dev/null @@ -1,519 +0,0 @@ -/* - json2.js - 2015-05-03 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. This file is provides the ES5 JSON capability to ES3 systems. - If a project might run on IE8 or earlier, then this file should be included. - This file does nothing on ES5 systems. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 - ? '0' + n - : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date - ? 'Date(' + this[key] + ')' - : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint - eval, for, this -*/ - -/*property - JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -if (typeof JSON !== 'object') { - JSON = {}; -} - -(function () { - 'use strict'; - - var rx_one = /^[\],:{}\s]*$/, - rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rx_four = /(?:^|:|,)(?:\s*\[)+/g, - rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 - ? '0' + n - : n; - } - - function this_value() { - return this.valueOf(); - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function () { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - Boolean.prototype.toJSON = this_value; - Number.prototype.toJSON = this_value; - String.prototype.toJSON = this_value; - } - - var gap, - indent, - meta, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - rx_escapable.lastIndex = 0; - return rx_escapable.test(string) - ? '"' + string.replace(rx_escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' - ? c - : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' - : '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) - ? String(value) - : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 - ? '[]' - : gap - ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' - : '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ': ' - : ':' - ) + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ': ' - : ':' - ) + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 - ? '{}' - : gap - ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' - : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - rx_dangerous.lastIndex = 0; - if (rx_dangerous.test(text)) { - text = text.replace(rx_dangerous, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if ( - rx_one.test( - text - .replace(rx_two, '@') - .replace(rx_three, ']') - .replace(rx_four, '') - ) - ) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' - ? walk({'': j}, '') - : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } -}()); diff --git a/test.html b/test.html deleted file mode 100644 index a8cc7a5..0000000 --- a/test.html +++ /dev/null @@ -1,2226 +0,0 @@ -<html> - -<head> - <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> - <meta content="utf-8" http-equiv="encoding"> - <title>Xcos</title> - - <!-- Loads and initializes the library --> - <script type="text/javascript" src="jquery/jquery-1.8.2.js"></script> - <script type="text/javascript" src="mxClient.min.js"></script> - <script type="text/javascript" src="editor/mxDefaultKeyHandler.js"></script> - <script type="text/javascript" src="handler/mxKeyHandler.js"></script> - <script type="text/javascript" src="jquery/farbtastic.js"></script> - - <link rel="stylesheet" href="jquery/farbtastic.css" type="text/css" /> - <link rel="stylesheet" href="jquery/jquery-ui.css"> - - <script type="text/javascript" src="details.js"></script> - <script type="text/javascript" src="setup.js"></script> - <script type="text/javascript" src="json2.js"></script> - <script type="text/javascript"> - function main(container, outline, toolbar, sidebar, status) { - // Checks if the browser is supported - if (!mxClient.isBrowserSupported()) { - // Displays an error message if the browser is not supported. - mxUtils.error('Browser is not supported!', 200, false); - } else { - // If connect preview is not moved away then getCellAt is used to detect the cell under - // the mouse if the mouse is over the preview shape in IE (no event transparency), ie. - // the built-in hit-detection of the HTML document will not be used in this case. - mxConnectionHandler.prototype.movePreviewAway = false; - mxConnectionHandler.prototype.waypointsEnabled = true; - mxGraph.prototype.resetEdgesOnConnect = false; - - // Enables guides - mxGraphHandler.prototype.guidesEnabled = true; - - // Alt disables guides - mxGuide.prototype.isEnabledForEvent = function(evt) { - return !mxEvent.isAltDown(evt); - }; - - // Enables snapping waypoints to terminals - mxEdgeHandler.prototype.snapToTerminals = true; - - // Assigns some global constants for general behaviour, eg. minimum - // size (in pixels) of the active region for triggering creation of - // new connections, the portion (100%) of the cell area to be used - // for triggering new connections, as well as some fading options for - // windows and the rubberband selection. - mxConstants.MIN_HOTSPOT_SIZE = 16; - mxConstants.DEFAULT_HOTSPOT = 1; - - // Workaround for Internet Explorer ignoring certain CSS directives - if (mxClient.IS_QUIRKS) { - document.body.style.overflow = 'hidden'; - new mxDivResizer(container); - new mxDivResizer(outline); - new mxDivResizer(toolbar); - new mxDivResizer(sidebar); - new mxDivResizer(status); - } - - // Creates a wrapper editor with a graph inside the given container. - // The editor is used to create certain functionality for the - // graph, such as the rubberband selection, but most parts - // of the UI are custom in this example. - var editor = new mxEditor(); - var graph = editor.graph; - var model = graph.getModel(); - - /* - Maverick - The following variable 'diagRoot' serves as the root element for the entire - diagram. - */ - var diagRoot = new XcosDiagram(null, model, null); - - graph.setPanning(true); - graph.setConnectable(true); - graph.setConnectableEdges(true); - graph.setDisconnectOnMove(false); - graph.foldingEnabled = false; - - // Disable highlight of cells when dragging from toolbar - graph.setDropEnabled(false); - - // Centers the port icon on the target port - graph.connectionHandler.targetConnectImage = true; - - // Does not allow dangling edges - graph.setAllowDanglingEdges(false); - - // Sets the graph container and configures the editor - editor.setGraphContainer(container); - - // Disables built-in context menu - mxEvent.disableContextMenu(document.body); - - // Configures automatic expand on mouseover - graph.panningHandler.autoExpand = true; - - /* - @jiteshjha, @pooja - Overrides mxGraphModel.getStyle to return a specific style - for edges that reflects their target terminal. - */ - - graph.model.getStyle = function(cell) { - var style = null; - if (cell != null) { - // Get style for the recently created mxCell. - style = mxGraphModel.prototype.getStyle.apply(this, arguments); - // If the mxCell is an edge and if it's a fully formed edge - if (this.isEdge(cell) && cell.source != null) { - var target = this.getTerminal(cell, false); - if (target != null) { - /* cell.name attribute defines the link name - so that it can be parsed in the XML during - XSLT transformation. - */ - var cellSource = cell.source; - while (cellSource.isEdge() == true) { - cellSource = cellSource.source; - } - if (cellSource.value == "ExplicitOutputPort" || cellSource.value == "ExplicitInputPort") { - if (style == null) { - style = 'ExplicitLink' + ';'; - } - cell.name = "ExplicitLink"; - } else if (cellSource.value == "ImplicitOutputPort" || cellSource.value == "ImplicitInputPort") { - if (style == null) { - style = 'ImplicitLink' + ';'; - } - cell.name = "ImplicitLink"; - } else if (cellSource.value == "CommandPort" || cellSource.value == "ControlPort") { - if (style == null) { - style = 'CommandControlLink' + ';'; - } - cell.name = "CommandControlLink"; - } - } - } - } - return style; - }; - - - // Creates a right-click menu - graph.panningHandler.factoryMethod = function(menu, cell, evt) { - - if (cell != null) { - - if (cell.value == "ExplicitInputPort" || cell.value == "ExplicitOutputPort" || cell.value == "CommandPort" || cell.value == "ControlPort") { - - } else if (cell.isEdge() == true) // @ToDo: Pooja: Different edge value cases. - { - - menu.addItem('Delete', 'images/delete2.png', function() { - editor.execute('delete'); - }); - var edgeformat = menu.addItem('Format', null, null); - - menu.addItem('Border Color', 'images/draw-brush.png', function() { - showColorWheel(graph, cell, 'edgeStrokeColor'); - - }, edgeformat); - menu.addItem('Text and Text Font', 'images/edit.png', function() { - showTextEditWindow(graph, cell); - }, edgeformat); - menu.addItem('Text Color', 'images/edit.png', function() { - showColorWheel(graph, cell, 'edgeTextColor'); - }, edgeformat); - - } else { - menu.addItem('Block Parameters...', 'images/gear.gif', function() { - showPropertiesWindow(graph, cell); - }); - - menu.addItem('Cut', 'images/cut.png', function() { - editor.execute('cut'); - }); - menu.addItem('Copy', 'images/copy.png', function() { - editor.execute('copy'); - }); - menu.addItem('Delete', 'images/delete2.png', function() { - editor.execute('delete'); - }); - - menu.addItem('Selection to superblock', 'images/superblock.png', function() { - // @ToDo: Pooja: Functionality to be put. - }); - var format = menu.addItem('Format', null, null); - - menu.addItem('Rotate', 'images/rotate.png', function() { - editor.execute('rotateCustom'); - }, format); - menu.addItem('Border Color', 'images/draw-brush.png', function() { - showColorWheel(graph, cell, 'vertexStrokeColor'); - - }, format); - menu.addItem('Fill Color', 'images/edit.png', function() { - showColorWheel(graph, cell, 'vertexFillColor'); - }, format); - menu.addItem('Details', null, function() { - // @ToDo: Pooja: Functionality to be put. - }); - } - } else { - menu.addItem('Undo', 'images/undo.png', function() { - editor.execute('undo'); - }); - menu.addItem('Redo', 'images/redo.png', function() { - editor.execute('redo'); - }); - menu.addItem('Paste', 'images/paste.png', function() { - editor.execute('paste'); - }); - - menu.addItem('Select all', 'images/selectall.png', function() { - editor.execute('selectAll'); - }); - - /* - Maverick - Added one more parameter to the setContext function. - */ - menu.addItem('Set Context', null, function() { - showSetContext(graph, diagRoot); - }); - - /* - Maverick - Added one more parameter to the setContext function. - */ - menu.addItem('Setup', 'images/setup.png', function() { - showSetupWindow(graph, diagRoot); - }); - - - menu.addItem('Zoom In', 'images/zoom_in.png', function() { - editor.execute('zoomIn'); - }); - menu.addItem('Zoom Out', 'images/zoom_out.png', function() { - editor.execute('zoomOut'); - }); - menu.addItem('Diagram background...', null, function() { - showColorWheel(graph, cell, 'bgColor'); - }); - } - - }; - - //var config = mxUtils.load('config/editor-commons.xml').getDocumentElement(); - var config = mxUtils.load('config/keyhandler-commons.xml').getDocumentElement(); - editor.configure(config); - - - /* - For a new edge on the graph, check if that edge satisfies one of the port constraints. - */ - graph.addEdge = function(edge, parent, source, target, index) { - - var edgeSource = source; - - // If the source of the edge is also an edge, find the port. - while (edgeSource.isEdge() == true) { - edgeSource = edgeSource.source; - } - - // If the edge violates any port constraints, return null. - if (!((edgeSource.getEdgeCount() == 0 && edgeSource.isVertex() && - target.getEdgeCount() == 0 && target.isVertex()) || - (edgeSource.getEdgeCount() <= 1 && source.isEdge()))) { - alert("Port is already connected, please select an please select an unconnected port or a valid link"); - } else if (edgeSource.value == "ExplicitOutputPort" && target.value != "ExplicitInputPort") { - alert("Explicit data output port must be connected to explicit data input port"); - } else if (edgeSource.value == "ExplicitInputPort" && target.value != "ExplicitOutputPort") { - alert("Explicit data input port must be connected to explicit data output port"); - } else if (edgeSource.value == "ImplicitOutputPort" && target.value != "ImplicitInputPort") { - alert("Implicit data output port must be connected to implicit data input port"); - } else if (edgeSource.value == "ImplicitInputPort" && target.value != "ImplicitOutputPort") { - alert("Implicit data input port must be connected to implicit data output port"); - } else if (edgeSource.value == "CommandPort" && target.value != "ControlPort") { - alert("Command port must be connected to control port"); - } else if (edgeSource.value == "ControlPort" && target.value != "CommandPort") { - alert("Control port must be connected to command port"); - } else { - // If the edge is legit, return the edge. - return mxGraph.prototype.addEdge.apply(this, arguments); - } - - return null; - } - - // Shows a "modal" window when double clicking a vertex. - graph.dblClick = function(evt, cell) { - // Do not fire a DOUBLE_CLICK event here as mxEditor will - // consume the event and start the in-place editor. - if (this.isEnabled() && - !mxEvent.isConsumed(evt) && - cell != null && - this.isCellEditable(cell)) { - if (!this.isHtmlLabel(cell)) { - this.startEditingAtCell(cell); - } else { - /* - var content = document.createElement('div'); - content.innerHTML = this.convertValueToString(cell); - showModalWindow(this, 'Properties', content, 400, 300); - */ - if (cell.isVertex() == true) { - showPropertiesWindow(graph, cell); - } - } - } - - // Disables any default behaviour for the double click - mxEvent.consume(evt); - }; - - // Returns a shorter label if the cell is collapsed and no - // label for expanded groups - graph.getLabel = function(cell) { - var tmp = mxGraph.prototype.getLabel.apply(this, arguments); // "supercall" - if (this.isCellLocked(cell)) { - // Returns an empty label but makes sure an HTML - // element is created for the label (for event - // processing wrt the parent label) - return ''; - } else if (this.isCellCollapsed(cell)) { - var index = tmp.indexOf('</h1>'); - if (index > 0) { - tmp = tmp.substring(0, index + 5); - } - } - return tmp; - } - - // Disables HTML labels for swimlanes to avoid conflict - // for the event processing on the child cells. HTML - // labels consume events before underlying cells get the - // chance to process those events. - // - // NOTE: Use of HTML labels is only recommended if the specific - // features of such labels are required, such as special label - // styles or interactive form fields. Otherwise non-HTML labels - // should be used by not overidding the following function. - // See also: configureStylesheet. - graph.isHtmlLabel = function(cell) { - return !this.isSwimlane(cell); - } - - graph.getTooltipForCell = function(cell) { - var text = null; - if (cell.isVertex() == true && cell.isConnectable() == false) { - var name = cell.value.getAttribute('blockElementName'); - var cellvar = cell.blockInstance.instance.details(); - - // If cell is a block or ports - if (cell.source == null && cell.target == null) { - if (cell.connectable) { // Cell is a Port - // @ToDo: Port Number - text = 'Style : ' + cell.style + "\n"; - } else { //Cell is a block - // @ToDo: Block Name, Simulation, Flip, Mirror - // @ToDo: Number of Input, Output, Control, Command Ports - var inputPort, outputPort, controlPort, commandPort; - if (cellvar.model.in.height == null) { - inputPort = 0; - } - else { - inputPort = cellvar.model.in.height; - } - if (cellvar.model.out.height == null) { - outputPort = 0; - } - else { - outputPort = cellvar.model.out.height; - } - if (cellvar.model.evtin.height == null) { - controlPort = 0; - } - else { - controlPort = cellvar.model.evtin.height; - } - if (cellvar.model.evtout.height == null) { - commandPort = 0; - } - else { - commandPort = cellvar.model.evtout.height; - } - var geometry = cell.getGeometry(); - text = 'Block Name : ' + cell.value.getAttribute('blockElementName') + "\n" + - 'Simulation : ' + cell.value.getAttribute('simulationFunctionName') + "\n" + - 'UID : ' + cell.id + "\n" + - 'Style : ' + cell.style + "\n" + - 'Flip : ' + getData(cellvar.graphics.flip)[0] + "\n" + - 'Mirror : false' + "\n" + - 'Input Ports : ' + inputPort + "\n" + - 'Output Ports : ' + outputPort + "\n" + - 'Control Ports : ' + controlPort + "\n" + - 'Command Ports : ' + commandPort + "\n" + - 'x : ' + geometry.x + "\n" + - 'y : ' + geometry.y + "\n" + - 'w : ' + geometry.width + "\n" + - 'h : ' + geometry.height + "\n"; - } - } - } - return text; - }; - - // Create XML tags! - // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - // https://jgraph.github.io/mxgraph/docs/js-api/files/model/mxCell-js.html - // Uncomment this block to see XML tags work - /*graph.convertValueToString = function(cell) - { - if (mxUtils.isNode(cell.value)) - { - return cell.getAttribute('label', ''); - } - };*/ - - var cellLabelChanged = graph.cellLabelChanged; - graph.cellLabelChanged = function(cell, newValue, autoSize) { - if (mxUtils.isNode(cell.value)) { - // Clones the value for correct undo/redo - var elt = cell.value.cloneNode(true); - elt.setAttribute('label', newValue); - newValue = elt; - } - - cellLabelChanged.apply(this, arguments); - }; - - // Enables new connections - graph.setConnectable(true); - - // Adds all required styles to the graph (see below) - configureStylesheet(graph); - - // Adds sidebar icons. - addIcons(graph, sidebar); - - // Creates a new DIV that is used as a toolbar and adds - // toolbar buttons. - var spacer = document.createElement('div'); - spacer.style.display = 'inline'; - spacer.style.padding = '8px'; - - // Defines a new export action - editor.addAction('toggle', function(editor, cell) { - var toggle = document.getElementById("toggleBlocks"); - var button = document.getElementById("toggle"); - toggle.click(); - button.innerHTML = ''; - if (toggle.innerHTML == 'Expand All') { - createButtonImage(button, 'images/navigate_plus.png'); - } else if (toggle.innerHTML == 'Collapse All') { - createButtonImage(button, 'images/navigate_minus.png'); - } - var titleName = document.createTextNode(toggle.innerHTML); - button.appendChild(titleName); - }); - - - // @jiteshjha, @pooja - /* - On selection and deletion of any block, 'deleteBlock' - function deletes all the associated edges with that block. - Used Preorder traversal for edges. - */ - editor.addAction('deleteBlock', function(editor, cell) { - var cells = []; - var selectionCells = graph.getSelectionCells(); - for (var k = 0; k < selectionCells.length; k++) { - var portCount = selectionCells[k].getChildCount(); - cells.push(selectionCells[k]); - // Finds all the port with edges of the selected cell, and calls getEdgeId() for - // each edge object of that port. - for (var i = 0; i < portCount; i++) { - var edgeCount = selectionCells[k].getChildAt(i).getEdgeCount(); - if (edgeCount != 0) { - getEdgeId(selectionCells[k].getChildAt(i)); - - for (var j = 0; j < edgeCount; j++) { - var edgeObject = selectionCells[k].getChildAt(i).getEdgeAt(j); - getEdgeId(edgeObject); - } - } - } - } - - - /* getEdgeId() find all the associated edges from an edge. - Pushes the object of that edge into an array of mxCell objects. - */ - function getEdgeId(edgeObject) { - var cellStack = []; - if (edgeObject != null && edgeObject.isEdge() == true) { - cellStack.push(edgeObject); - while (cellStack.length != 0) { - var tempEdgeObject = cellStack.pop(); - if (tempEdgeObject.edge == true && (cells.indexOf(tempEdgeObject) == -1)) { - cells.push(tempEdgeObject); - } - for (var j = 0; j < tempEdgeObject.getEdgeCount(); j++) { - cellStack.push(tempEdgeObject.getEdgeAt(j)); - } - } - } - } - - // The mxCells to be deleted are first highlighted, - // and then the selection is deleted in a single go. - graph.getSelectionModel().setCells(cells); - editor.execute('delete'); - }); - - addToolbarButton(editor, toolbar, 'toggle', 'Expand All', 'images/navigate_plus.png'); - toolbar.appendChild(spacer.cloneNode(true)); - - addToolbarButton(editor, toolbar, 'cut', 'Cut', 'images/cut.png'); - addToolbarButton(editor, toolbar, 'copy', 'Copy', 'images/copy.png'); - addToolbarButton(editor, toolbar, 'paste', 'Paste', 'images/paste.png'); - - toolbar.appendChild(spacer.cloneNode(true)); - - addToolbarButton(editor, toolbar, 'delete', '', 'images/delete2.png'); - addToolbarButton(editor, toolbar, 'undo', '', 'images/undo.png'); - addToolbarButton(editor, toolbar, 'redo', '', 'images/redo.png'); - toolbar.appendChild(spacer.cloneNode(true)); - - addToolbarButton(editor, toolbar, 'show', 'Show', 'images/camera.png'); - addToolbarButton(editor, toolbar, 'print', 'Print', 'images/printer.png'); - - toolbar.appendChild(spacer.cloneNode(true)); - - - /* - Maverick - This method is used for loading the stylesheet from the file. - Reference: http://www.w3schools.com/xsl/xsl_client.asp - */ - - function loadXMLDoc(filename) { - if (window.ActiveXObject) { - xhttp = new ActiveXObject("Msxml2.XMLHTTP"); - } else { - xhttp = new XMLHttpRequest(); - } - xhttp.open("GET", filename, false); - try { - xhttp.responseType = "msxml-document" - } catch (err) {} - xhttp.send(""); - return xhttp.responseXML; - } - - - /* - Maverick - The Export buttons in toolbar call this function with varying - arguments. - The third argument is used to decide which button is being - pressed. - exportXML : 2 arguments - exportXcos: 3 arguments - */ - function displayXMLorXcos() { - var textarea = document.createElement('textarea'); - textarea.style.width = '400px'; - textarea.style.height = '400px'; - var enc = new mxCodec(mxUtils.createXmlDocument()); - /*var array=[],key; - for (key in diagRoot.model.cells) { - - if(diagRoot.model.cells[key].connectable == false) - { - array.push(diagRoot.model.cells[key].inst); - diagRoot.model.cells[key].inst=null; - } - }*/ - var node = enc.encode(diagRoot); - - var str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + mxUtils.getPrettyXml(node); - - textarea.value = str; - /*var j = 0; - for (key in diagRoot.model.cells) { - - if(diagRoot.model.cells[key].connectable == false) - { - diagRoot.model.cells[key].inst=array[j++]; - } - }*/ - if (arguments[2] == null) { - showModalWindow(graph, 'XML', textarea, 410, 440); - } else { - - return mxUtils.getPrettyXml(node); - } - } - - // Defines a new export action - editor.addAction('exportXML', function(editor, cell) { - //Only two parameters passed here. - displayXMLorXcos(editor, cell); - }); - - /* Maverick - Reference: http://www.w3schools.com/xsl/xsl_client.asp - */ - - editor.addAction('exportXcos', function(editor, cell) { - //Mind the 3 parameters. - var xmlFromExportXML = displayXMLorXcos(editor, cell, true); - if (xmlFromExportXML == null) alert('First create the XML file.'); - else { - - var xml = mxUtils.parseXml(xmlFromExportXML); - - var xsl = loadXMLDoc("finalmodsheet.xsl"); - - xsltProcessor = new XSLTProcessor(); - xsltProcessor.importStylesheet(xsl); - resultDocument = xsltProcessor.transformToDocument(xml); - - - var textarea = document.createElement('textarea'); - textarea.style.width = '400px'; - textarea.style.height = '400px'; - /* - Maverick - Using resultDocument.documentElement to remove an additional tag "<#document>" created by the XSLTProcessor. - */ - var str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" + mxUtils.getPrettyXml(resultDocument.documentElement); - - textarea.value = str.replace(/\n\n/g, "\n"); - showModalWindow(graph, 'Xcos', textarea, 410, 440); - } - }); - - addToolbarButton(editor, toolbar, 'exportXML', 'Export XML', 'images/export1.png'); - - addToolbarButton(editor, toolbar, 'exportXcos', 'Export Xcos', 'images/export1.png'); - - // Adds toolbar buttons into the status bar at the bottom - // of the window. - - addToolbarButton(editor, status, 'zoomIn', '', 'images/zoom_in.png', true); - addToolbarButton(editor, status, 'zoomOut', '', 'images/zoom_out.png', true); - addToolbarButton(editor, status, 'actualSize', '', 'images/view_1_1.png', true); - addToolbarButton(editor, status, 'fit', '', 'images/fit_to_size.png', true); - - // Creates the outline (navigator, overview) for moving - // around the graph in the top, right corner of the window. - var outln = new mxOutline(graph, outline); - - // To show the images in the outline, uncomment the following code - //outln.outline.labelsVisible = true; - //outln.outline.setHtmlLabels(true); - - // Fades-out the splash screen after the UI has been loaded. - var splash = document.getElementById('splash'); - if (splash != null) { - try { - mxEvent.release(splash); - mxEffects.fadeOut(splash, 100, true); - } catch (e) { - - // mxUtils is not available (library not loaded) - splash.parentNode.removeChild(splash); - } - } - - // Handles cursor keys - guides.html - var nudge = function(keyCode) { - if (!graph.isSelectionEmpty()) { - var dx = 0; - var dy = 0; - if (keyCode == 37) { - dx = -5; - } else if (keyCode == 38) { - dy = -5; - } else if (keyCode == 39) { - dx = 5; - } else if (keyCode == 40) { - dy = 5; - } - graph.moveCells(graph.getSelectionCells(), dx, dy); - } - }; - // Transfer initial focus to graph container for keystroke handling - // graph.container.focus(); - // Handles keystroke events - var keyHandler = new mxKeyHandler(graph); - keyHandler.bindKey(37, function() { - nudge(37); - }); - keyHandler.bindKey(38, function() { - nudge(38); - }); - keyHandler.bindKey(39, function() { - nudge(39); - }); - keyHandler.bindKey(40, function() { - nudge(40); - }); - - // Starts connections on the background in wire-mode - var connectionHandlerIsStartEvent = graph.connectionHandler.isStartEvent; - graph.connectionHandler.isStartEvent = function(me) { - return connectionHandlerIsStartEvent.apply(this, arguments); - }; - - // Avoids any connections for gestures within tolerance except when in wire-mode - // or when over a port - var connectionHandlerMouseUp = graph.connectionHandler.mouseUp; - graph.connectionHandler.mouseUp = function(sender, me) { - if (this.first != null && this.previous != null) { - var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY()); - var dx = Math.abs(point.x - this.first.x); - var dy = Math.abs(point.y - this.first.y); - - if (dx < this.graph.tolerance && dy < this.graph.tolerance) { - // Selects edges in non-wire mode for single clicks, but starts - // connecting for non-edges regardless of wire-mode - if (this.graph.getModel().isEdge(this.previous.cell)) { - this.reset(); - } - - return; - } - } - - connectionHandlerMouseUp.apply(this, arguments); - }; - - mxEvent.disableContextMenu(container); - - // @Adhitya: Add focus to a mxCell - if (mxClient.IS_NS) { - mxEvent.addListener(graph.container, 'mousedown', function(evt) { - if (!graph.isEditing()) { - graph.container.setAttribute('tabindex', '-1'); - graph.container.focus(); - } - }); - } - - } - }; - - /* - @jiteshjha - styleToObject(style) converts style string into an object. - Format : First item in the object will be 'default: linkStyle', - and the rest of items will be of the style 'mxConstants:value' - */ - - function styleToObject(style) { - - var defaultStyle = style.substring(0, style.indexOf(';')); - var styleObject = { - "default": defaultStyle - }; - var remainingStyle = style.substring(style.indexOf(';') + 1); - - /* - remainingStyle is the string without the default style. - For every key:value pair in the string, - extract the key(string before '=') and the value - (string before ';'), set the key:value pair into styleObject - and remainingStyle is set to a string without the key:value pair. - */ - while (remainingStyle.length > 0) { - var indexOfKey = remainingStyle.indexOf('='); - var key = remainingStyle.substring(0, indexOfKey); - remainingStyle = remainingStyle.substring(indexOfKey + 1); - var indexOfValue = remainingStyle.indexOf(';'); - var value = remainingStyle.substring(0, indexOfValue); - styleObject[key] = value; - remainingStyle = remainingStyle.substring(indexOfValue + 1); - } - - return styleObject; - } - - /* - @jiteshjha - styleToObject(style) converts the object back to the style string. - */ - function objectToStyle(object) { - var style = ""; - for (var key in object) { - if (key.toString() == "default") { - style += object[key] + ';'; - } else { - style += (key + '=' + object[key] + ';'); - } - } - return style; - } - - /* - Maverick - The following function is used to define a tag for entire diagram. - We can set context, model and setup parameters for the entire diagram - using this function. - */ - - - function XcosDiagram(context, model, attributes) { - this.context = context; - this.model = model; - this.finalIntegrationTime = attributes; - } - - - /* - @jiteshjha, @pooja - setContext dialog box - Includes a set context instruction text and input text area. - */ - - /* - Maverick - Added 'diagRoot' parameter. - */ - function showSetContext(graph, diagRoot) { - - // Create basic structure for the form - var content = document.createElement('div'); - content.setAttribute("id", "setContext"); - - // Add Form - var myform = document.createElement("form"); - myform.method = ""; - myform.setAttribute("id", "formProperties"); - - // Add set context string - var descriptionSetContext = document.createElement("div"); - descriptionSetContext.innerHTML = "You may enter here scilab instructions to define symbolic parameters used in block definitions using Scilab instructions. These instructions are evaluated once confirmed(i.e. you click on OK and every time the diagram is loaded)"; - descriptionSetContext.setAttribute("id", "descriptionSetContext"); - myform.appendChild(descriptionSetContext); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // input text area - var textareaSetContext = document.createElement("textarea"); - textareaSetContext.setAttribute("id", "textareaSetContext"); - - myform.appendChild(textareaSetContext); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Button - Submit - var btn = document.createElement("button"); - btn.innerHTML = 'Ok'; - btn.type = "button"; - btn.name = "submit"; - btn.setAttribute("id", "buttonSetContext"); - - var contextValue = handleContext("get"); - - var displayValue = ""; - - /* - Maverick - Modified the for loop because only requirement was to - traverse the array of 'contextValue' and not all the - elements of it. - */ - for (var i = 0; i < contextValue.length; i++) { - displayValue += contextValue[i] + "\n"; - } - if (contextValue != "") { - textareaSetContext.value = displayValue; - } else { - textareaSetContext.value = ""; - - } - - // Executes when button 'btn' is clicked - btn.onclick = function() { - - var input = document.getElementById('textareaSetContext').value; - - /* - Maverick - Code to extract context parameter values from the text area - containing the input. - */ - var contextValues = []; - var i = 0, - temp = ""; - for (i = 0; i < input.length; i++) { - if (input[i] == '\n') { - if (temp != "") { - contextValues.push(temp); - } - temp = ""; - continue; - } - temp += input[i]; - } - if (temp != "") { - contextValues.push(temp); - } - - diagRoot.context = contextValues; - diagRoot.context.scilabClass = "String[]"; - handleContext("set", contextValues); - wind.destroy(); - }; - - myform.appendChild(btn); - content.appendChild(myform); - var wind = showModalWindow(graph, 'Set Context', content, 450, 350); - }; - - function showPropertiesWindow(graph, cell) { - - var name = cell.getAttribute('blockElementName'); - var defaultProperties = cell.blockInstance.instance.get(); //window[name]("get"); - /*{ - nbr_curves: ["Number of curves", 1], - clrs: ["color (>0) or mark (<0)", [1, 2, 3, 4, 5, 6, 7, 13]], - siz: ["line or mark size", [1, 1, 1, 1, 1, 1, 1, 1]], - win: ["Output window number (-1 for automatic)", -1], - wpos: ["Output window position", [-1, -1]], - wdim: ["Output window sizes", [-1, -1]], - vec_x: ["Xmin and Xmax", [-15, 15]], - vec_y: ["Ymin and Ymax", [-15, 15]], - vec_z: ["Zmin and Zmax", [-15, 15]], - param3ds: ["Alpha and Theta", [50, 280]], - N: ["Buffer size", 2] - };*/ - - //var defaultProperties=window["CONST_m"]("get"); - - // Create basic structure for the form - var content = document.createElement('div'); - content.setAttribute("id", "contentProperties"); - - // Heading of content - var heading = document.createElement('h2'); - heading.innerHTML = "Set Scope Parameters"; - heading.id = "headingProperties" - content.appendChild(heading); - - // Add Form - var myform = document.createElement("form"); - myform.method = "post"; - myform.id = "formProperties"; - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - - // Input Title - var fieldName = defaultProperties[key]; - var namelabel = document.createElement('label'); - namelabel.innerHTML = defaultProperties[key][0]; - myform.appendChild(namelabel); - - // Input - var input = document.createElement("input"); - input.name = key; - input.value = defaultProperties[key][1]; - input.setAttribute("id", key.toString()); - input.setAttribute("class", "fieldInput"); - myform.appendChild(input); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - } - } - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Button - Submit - var btn = document.createElement("button"); - btn.innerHTML = 'Submit'; - btn.type = "button"; - btn.name = "submit"; - - // Executes when button 'btn' is clicked - btn.onclick = function() { - var propertiesObject = { - id: cell.id - }; - - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - propertiesObject[key] = document.getElementById(key.toString()).value; - } - } - var details = cell.blockInstance.instance.set(propertiesObject); //window[name]("set",cell.value,propertiesObject); - var enc = new mxCodec(); - var node = enc.encode(details); - node.setAttribute('label', getData(details.exprs)[0]); - cell.value = node; - /* - Maverick - We have changed the value of the cell, but the change won't be reflected - unless the graph is refreshed. - */ - graph.refresh(); - wind.destroy(); - }; - myform.appendChild(btn); - - // Button - Reset - var btn = document.createElement("button"); - btn.innerHTML = 'Reset'; - btn.type = "button"; - btn.name = "submit"; - btn.id = "resetButtonProperties"; - btn.onclick = function() { - // Reset - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - var element = document.getElementById(key.toString()); - element.value = defaultProperties[key][1]; - } - } - }; - - myform.appendChild(btn); - // Base height without fields : 135 px - height = 135 + 26 * defaultProperties.length + 15; - - content.appendChild(myform); - var wind = showModalWindow(graph, 'Properties', content, 450, height); - }; - - /* - @jiteshjha - Creates a dialog box related to the edge label properties. - The properties implemented are : edge label, label fontStyle, - label fontSize, label fontStyle. - */ - - - function showTextEditWindow(graph, cell) { - var fontFamilyList = { - "Arial": 0, - "Dialog": 1, - "Verdana": 2, - "Times New Roman": 3 - } - var defaultProperties = { - text: ["Text", "text"], - fontFamily: ["Font Family", fontFamilyList], - fontSize: ["fontSize", 20] - }; - - var style = graph.getModel().getStyle(cell); - var styleObject = styleToObject(style); - if ('fontSize' in styleObject) { - defaultProperties['fontSize'][1] = styleObject['fontSize']; - } - if (cell.value != "") { - defaultProperties['text'][1] = cell.value; - } - - // Create basic structure for the form - var content = document.createElement('div'); - content.setAttribute("id", "contentProperties"); - - // Heading of content - var heading = document.createElement('h2'); - heading.innerHTML = "Text and Text Font"; - heading.id = "headingProperties" - content.appendChild(heading); - - // Add Form - var myform = document.createElement("form"); - myform.method = "post"; - myform.id = "formProperties"; - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - - // Input Title - var fieldName = defaultProperties[key]; - var namelabel = document.createElement('label'); - namelabel.innerHTML = defaultProperties[key][0]; - myform.appendChild(namelabel); - - if (key == "fontFamily") { - //Here we create a "select" element (a drop down list). - var newList = document.createElement("select"); - newList.style.cssText = "float:right"; - newList.setAttribute("id", key.toString()); - var dropdownItems = defaultProperties[key][1]; - - for (var item in dropdownItems) { - if (dropdownItems.hasOwnProperty(item)) { - option = document.createElement('option'); - option.value = item; - option.text = item; - option.setAttribute("id", item); - newList.appendChild(option); - } - } - - var selectedFontFamily = 0; - var styleObject = styleToObject(style); - if ('fontFamily' in styleObject) { - selectedFontFamily = styleObject['fontFamily']; - } - newList.selectedIndex = dropdownItems[selectedFontFamily]; - myform.appendChild(newList); - } else { - var input = document.createElement("input"); - input.name = key; - input.value = defaultProperties[key][1]; - input.setAttribute("id", key.toString()); - input.setAttribute("class", "fieldInput"); - myform.appendChild(input); - } - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - } - } - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - /* - changeFontStyle function sets the style for given fontStyle and toggles with the active class - for "set" type, and toggles with the active class for "get" type. - */ - function changeFontStyle(type, graph, cell, button, bit) { - var style = graph.getModel().getStyle(cell); - var trigger = document.getElementById(button); - var styleObject = styleToObject(style); - var previousValue = 1; - if ('fontStyle' in styleObjesct) { - previousValue = styleObject['fontStyle']; - - // To get a bit mask: - var mask = 1 << bit; // Get the 1st element - - if (type == "get") { - // toggle the bit - previousValue ^= mask; - trigger.classList.toggle(button); - styleObject['fontStyle'] = previousValue; - style = objectToStyle(styleObject); - graph.getModel().setStyle(cell, style); - } else if (type == "set") { - if ((previousValue & mask) != 0) { - trigger.classList.toggle(button); - } - } - } - } - - // Button - Bold - var btn = document.createElement("button"); - btn.innerHTML = 'Bold'; - btn.setAttribute("id", "boldButton"); - btn.type = "button"; - btn.name = "submit"; - btn.onclick = function() { - changeFontStyle("get", graph, cell, 'boldButton', 0); - } - myform.appendChild(btn); - - // Button - Italics - var btn = document.createElement("button"); - btn.innerHTML = 'Italic'; - btn.setAttribute("id", "italicButton"); - btn.type = "button"; - btn.name = "submit"; - btn.onclick = function() { - changeFontStyle("get", graph, cell, 'italicButton', 1); - } - myform.appendChild(btn); - - // Button - Underline - var btn = document.createElement("button"); - btn.innerHTML = 'Underline'; - btn.setAttribute("id", "underlineButton"); - btn.type = "button"; - btn.name = "submit"; - btn.onclick = function() { - changeFontStyle("get", graph, cell, 'underlineButton', 2); - } - myform.appendChild(btn); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Button - Submit - var btn = document.createElement("button"); - btn.innerHTML = 'Submit'; - btn.type = "button"; - btn.name = "submit"; - - // Executes when button 'btn' is clicked - btn.onclick = function() { - var propertiesObject = { - id: cell.id - }; - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - propertiesObject[key] = document.getElementById(key.toString()).value; - } - } - var style = graph.getModel().getStyle(cell); - var styleObject = styleToObject(style); - styleObject['fontSize'] = propertiesObject['fontSize']; - styleObject['fontFamily'] = propertiesObject['fontFamily']; - style = objectToStyle(styleObject); - graph.getModel().setStyle(cell, style); - graph.getModel().setValue(cell, propertiesObject['text']); - wind.destroy(); - }; - myform.appendChild(btn); - - // Base heights without fields : 135 px - height = 135 + 26 * defaultProperties.length + 15; - content.appendChild(myform); - var wind = showModalWindow(graph, 'Text and Text font', content, 450, height); - - /* - @jiteshjha - If any fontStyle(Bold, Italic, Underline) has already been implemented - for the selected edge label, add the respective active class to that button. - */ - - if ('fontStyle' in styleObject) { - changeFontStyle("set", graph, cell, 'boldButton', 0); - changeFontStyle("set", graph, cell, 'italicButton', 1); - changeFontStyle("set", graph, cell, 'underlineButton', 2); - } - }; - /* - @jiteshjha, @pooja - showSetupWindow dialog box - */ - - /* - Maverick - Added 'diagRoot' parameter. - */ - function showSetupWindow(graph, diagRoot) { - - /* - Maverick - Added one more element in the list for each key to be used in the <XcosDiagram> - tag. - */ - - var defaultProperties = setup("get"); - - // Create basic structure for the form - var content = document.createElement('div'); - content.setAttribute("id", "contentProperties"); - - // Heading of content - var heading = document.createElement('h2'); - heading.innerHTML = "Setup"; - heading.id = "headingProperties" - content.appendChild(heading); - - // Add Form - var myform = document.createElement("form"); - myform.method = "post"; - myform.id = "formProperties"; - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - - // Input Title - var fieldName = defaultProperties[key]; - var namelabel = document.createElement('label'); - namelabel.innerHTML = defaultProperties[key][0]; - myform.appendChild(namelabel); - - if (key == "solv_kind") { - - //Here we create a "select" element (a drop down list). - var newList = document.createElement("select"); - newList.style.cssText = "float:right"; - newList.setAttribute("id", key.toString()); - var dropdownItems = setup("getArray"); - - // Iterate over the dropdown options and create html elements - dropdownItems.forEach(function(value, i) { - option = document.createElement('option'); - option.value = i.toFixed(1); - option.text = value; - newList.appendChild(option); - }); - newList.selectedIndex = defaultProperties[key][2]; - myform.appendChild(newList); - - } else { - var input = document.createElement("input"); - input.name = key; - input.value = defaultProperties[key][2]; - input.setAttribute("id", key.toString()); - input.setAttribute("class", "fieldInput"); - myform.appendChild(input); - } - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - } - } - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Button - Set Context - var btn = document.createElement("button"); - btn.innerHTML = 'Set Context'; - btn.style.cssText = 'float: left'; - btn.type = "button"; - btn.name = "submit"; - btn.id = "resetButtonProperties"; - btn.onclick = function() { - // show Set Context - /* - Maverick - Added the parameter here as well. - */ - showSetContext(graph, diagRoot); - }; - myform.appendChild(btn); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - - // Button - Submit - var btn = document.createElement("button"); - btn.innerHTML = 'Submit'; - btn.type = "button"; - btn.name = "submit"; - - // Executes when button 'btn' is clicked - btn.onclick = function() { - var propertiesObject = {}; - - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - propertiesObject[defaultProperties[key][1]] = document.getElementById(key.toString()).value; - - /* - Maverick - Adding the corresponding attributes to the <XcosDiagram> tag. - */ - diagRoot[defaultProperties[key][1]] = document.getElementById(key.toString()).value; - } - } - - setup("set", propertiesObject); - wind.destroy(); - }; - - myform.appendChild(btn); - - - // Button - Reset - var btn = document.createElement("button"); - btn.innerHTML = 'Reset'; - btn.type = "button"; - btn.name = "submit"; - btn.id = "resetButtonProperties"; - btn.onclick = function() { - // Reset - for (var key in defaultProperties) { - if (defaultProperties.hasOwnProperty(key)) { - var element = document.getElementById(key.toString()); - if (key != "solv_kind") { - element.value = defaultProperties[key][2]; - } else { - /* - Maverick - Code modified to reset the drop down list. - */ - element.selectedIndex = 0; - } - } - } - }; - - myform.appendChild(btn); - // Base height without fields : 135 px - height = 135 + 26 * defaultProperties.length + 15; - - content.appendChild(myform); - var wind = showModalWindow(graph, 'Set Parameters', content, 450, height); - }; - - function showColorWheel(graph, cell, selectProperty) { - // Create basic structure for the form - var content = document.createElement('div'); - content.setAttribute("id", "colorProperties"); - // Add Form - var myform = document.createElement("form"); - myform.method = ""; - myform.setAttribute("id", "formProperties"); - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - // Input Title - var fieldName = 'Color'; - var namelabel = document.createElement('label'); - namelabel.innerHTML = fieldName; - myform.appendChild(namelabel); - // Input - var input = document.createElement("input"); - input.name = fieldName; - input.value = 0; - input.style.cssText = 'float: right;'; - input.setAttribute("id", "color"); - myform.appendChild(input); - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - var picker = document.createElement('div'); - picker.setAttribute("id", "picker"); - myform.appendChild(picker); - // Line break - var linebreak = document.createElement('br'); - myform.appendChild(linebreak); - // Button - Submit - var btn = document.createElement("button"); - btn.innerHTML = 'Submit'; - btn.type = "button"; - btn.name = "submit"; - btn.style.cssText = 'margin-left: 75px'; - // Executes when button 'btn' is clicked - btn.onclick = function() { - var input = document.getElementById('color').value; - var style = graph.getModel().getStyle(cell); - var styleObject = styleToObject(style); - if (selectProperty == "edgeStrokeColor") { - styleObject['strokeColor'] = input; - } else if (selectProperty == "bgColor") { - graph.container.style.backgroundColor = input; - } else if (selectProperty == "vertexStrokeColor") { - styleObject['strokeColor'] = input; - } else if (selectProperty == "vertexFillColor") { - styleObject['fillColor'] = input; - } else if (selectProperty == "edgeTextColor") { - styleObject['fontColor'] = input; - } - style = objectToStyle(styleObject); - graph.getModel().setStyle(cell, style); - wind.destroy(); - }; - myform.appendChild(btn); - content.appendChild(myform); - var wind = showModalWindow(graph, 'Diagram background...', content, 285, 340); - // Invokes the farbtastic functionality - $(document).ready(function() { - $('#picker').farbtastic('#color'); - }); - }; - - function createButtonImage(button, image) { - if (image != null) { - var img = document.createElement('img'); - img.setAttribute('src', image); - img.style.width = '16px'; - img.style.height = '16px'; - img.style.verticalAlign = 'middle'; - img.style.marginRight = '2px'; - button.appendChild(img); - } - } - - function addIcons(graph, sidebar) { - var req = mxUtils.load('palettes/palettes.xml'); - var root = req.getDocumentElement(); - var x = root.getElementsByTagName('node')[0]; - var categories = x.getElementsByTagName('node'); - for (var i = 0, nodeLength = categories.length; i < nodeLength; i++) { - var categoryName = categories[i].getAttribute('name'); - var title = document.createElement('h3'); - title.setAttribute('class', 'accordion-header ui-accordion-header ui-helper-reset ui-state-default ui-accordion-icons ui-corner-all'); - var span = document.createElement('span'); - span.setAttribute('class', 'ui-accordion-header-icon ui-icon ui-icon-triangle-1-e'); - var titleName = document.createTextNode(categoryName); - title.appendChild(span); - title.appendChild(titleName); - sidebar.appendChild(title); - var newImages = document.createElement('div'); - newImages.setAttribute('class', 'ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom'); - var blocks = categories[i].getElementsByTagName('block'); - for (var j = 0, blockLength = blocks.length; j < blockLength; j++) { - var name = blocks[j].getAttribute('name'); - var icon = blocks[j].getElementsByTagName('icon')[0]; - var iconPath = icon.getAttribute('path'); - addSidebarIcon(graph, newImages, name, iconPath); - } - sidebar.appendChild(newImages); - } - } - - function getImgHTML(name) { - return '<img src="' + 'blocks/' + name + '.svg' + '" height="80" width="80">'; - } - - function addToolbarButton(editor, toolbar, action, label, image, isTransparent) { - var button = document.createElement('button'); - button.style.fontSize = '10'; - createButtonImage(button, image); - if (isTransparent) { - button.style.background = 'transparent'; - button.style.color = '#FFFFFF'; - button.style.border = 'none'; - } - mxEvent.addListener(button, 'click', function(evt) { - editor.execute(action); - }); - mxUtils.write(button, label); - button.setAttribute('id', action); - toolbar.appendChild(button); - }; - - function showModalWindow(graph, title, content, width, height) { - var background = document.createElement('div'); - background.style.position = 'absolute'; - background.style.left = '0px'; - background.style.top = '0px'; - background.style.right = '0px'; - background.style.bottom = '0px'; - background.style.background = 'black'; - mxUtils.setOpacity(background, 50); - document.body.appendChild(background); - - if (mxClient.IS_IE) { - new mxDivResizer(background); - } - - var x = Math.max(0, document.body.scrollWidth / 2 - width / 2); - var y = Math.max(10, (document.body.scrollHeight || document.documentElement.scrollHeight) / 2 - height * 2 / 3); - var wind = new mxWindow(title, content, x, y, width, height, false, true); - wind.setClosable(true); - - // Fades the background out after after the window has been closed - wind.addListener(mxEvent.DESTROY, function(evt) { - graph.setEnabled(true); - mxEffects.fadeOut(background, 50, true, 10, 30, true); - }); - - graph.setEnabled(false); - graph.tooltipHandler.hide(); - wind.setVisible(true); - return wind; - }; - - var flag = 0; - - function addSidebarIcon(graph, sidebar, name, image) { - // Function that is executed when the image is dropped on - // the graph. The cell argument points to the cell under - // the mousepointer if there is one. - var funct = function(graph, evt, cell, x, y) { - var parent = graph.getDefaultParent(); - var model = graph.getModel(); - var v1 = null; - var doc = mxUtils.createXmlDocument(); - model.beginUpdate(); - try { - var label = getImgHTML(name); // Will not exist for all blocks - var details_instance = new window[name](); - var details = details_instance.define(); - var enc = new mxCodec(mxUtils.createXmlDocument()); - var node = enc.encode(details); - node.setAttribute('label', label); - var temp = enc.encode(parent); - node.setAttribute('parent', temp.getAttribute('id')); - var i, arr = []; - var blockModel = details_instance.x.model; - var graphics = details_instance.x.graphics; - - /* To determine number and type of Port*/ - var inputPorts = [], - outputPorts = [], - controlPorts = [], - commandPorts = []; - if (blockModel.in.height != null) { - arr = getData(graphics.in_implicit); - if (arr.length != 0) { - inputPorts = arr; - } else { - for (i = 0; i < blockModel.in.height; i++) { - inputPorts.push("E"); - } - } - } - if (blockModel.out.height != null) { - arr = getData(graphics.out_implicit); - if (arr.length != 0) { - outputPorts = arr; - } else { - for (i = 0; i < blockModel.out.height; i++) { - outputPorts.push("E"); - } - } - } - if (blockModel.evtin.height != null) { - for (i = 0; i < blockModel.evtin.height; i++) { - controlPorts.push("CONTROL"); - } - } - if (blockModel.evtout.height != null) { - for (i = 0; i < blockModel.evtout.height; i++) { - commandPorts.push("COMMAND"); - } - } - v1 = graph.insertVertex(parent, null, node, x, y, 80, 80, name); - // @Chhavi: Additional attribute to store the block's instance - v1.blockInstance = createInstanceTag(details_instance); - createPorts(graph, v1, inputPorts, controlPorts, outputPorts, commandPorts); - v1.setConnectable(false); - } finally { - model.endUpdate(); - } - graph.setSelectionCell(v1); - } - - var para = document.createElement('p'); - var blockFigure = document.createElement('figure'); - var img = document.createElement('img'); - img.setAttribute('src', image); - var caption = document.createElement('figcaption'); - var blockName = document.createTextNode(name); - caption.appendChild(blockName); - blockFigure.appendChild(img); - blockFigure.appendChild(caption); - para.appendChild(blockFigure); - sidebar.appendChild(para); - - var dragElt = document.createElement('div'); - dragElt.style.border = 'dashed black 1px'; - dragElt.style.width = '80px'; - dragElt.style.height = '80px'; - - // Creates the image which is used as the drag icon (preview) - var ds = mxUtils.makeDraggable(img, graph, funct, dragElt, 0, 0, true, true); - ds.setGuidesEnabled(true); - }; - - // Create ports - function createPorts(graph, block, left, top, right, bottom) { - createInputPorts(graph, block, left, top); - createOutputPorts(graph, block, right, bottom); - } - - function createInputPorts(graph, block, leftArray, topArray) { - var topNumber = topArray.length; - var leftNumber = leftArray.length; - if (leftNumber != 0) { - for (var i = 1; i <= leftNumber; i++) { - var x = 0; - var y = (i / (leftNumber + 1)).toFixed(4); - var portType = leftArray[i - 1]; - createInputPort(graph, block, x, y, portType, 'left', i); - } - } - if (topNumber != 0) { - for (var i = 1; i <= topNumber; i++) { - var x = (i / (topNumber + 1)).toFixed(4); - var y = 0; - var portType = topArray[i - 1]; - createInputPort(graph, block, x, y, portType, 'top', i); - } - } - }; - - function createOutputPorts(graph, block, rightArray, bottomArray) { - var bottomNumber = bottomArray.length; - var rightNumber = rightArray.length; - if (rightNumber != 0) { - for (var i = 1; i <= rightNumber; i++) { - var x = 1; - var y = (i / (rightNumber + 1)).toFixed(4); - var portType = rightArray[i - 1]; - createOutputPort(graph, block, x, y, portType, 'right', i); - } - } - if (bottomNumber != 0) { - for (var i = 1; i <= bottomNumber; i++) { - var x = (i / (bottomNumber + 1)).toFixed(4); - var y = 1; - var portType = bottomArray[i - 1]; - createOutputPort(graph, block, x, y, portType, 'bottom', i); - } - } - }; - - function createInputPort(graph, block, x, y, portType, position, ordering) { - var port = null; - if (portType == 'COMMAND') { - port = graph.insertVertex(block, null, 'CommandPort', x, y, 10, 10, 'CommandPort', true); - } else if (portType == 'CONTROL') { - port = graph.insertVertex(block, null, 'ControlPort', x, y, 10, 10, 'ControlPort', true); - } else if (portType == 'I') { - port = graph.insertVertex(block, null, 'ImplicitInputPort', x, y, 10, 10, 'ImplicitInputPort', true); - } else if (portType == 'E') { - port = graph.insertVertex(block, null, 'ExplicitInputPort', x, y, 10, 10, 'ExplicitInputPort', true); - } - if (port != null) { - if (position == 'top') { - port.geometry.offset = new mxPoint(-6, -10); - } else if (position == 'left') { - port.geometry.offset = new mxPoint(-10, -6); - } - port.ordering = ordering; - } - }; - - function createOutputPort(graph, block, x, y, portType, position, ordering) { - var port = null; - if (portType == 'COMMAND') { - port = graph.insertVertex(block, null, 'CommandPort', x, y, 10, 10, 'CommandPort', true); - } else if (portType == 'CONTROL') { - port = graph.insertVertex(block, null, 'ControlPort', x, y, 10, 10, 'ControlPort', true); - } else if (portType == 'I') { - port = graph.insertVertex(block, null, 'ImplicitOutputPort', x, y, 10, 10, 'ImplicitOutputPort', true); - } else if (portType == 'E') { - port = graph.insertVertex(block, null, 'ExplicitOutputPort', x, y, 10, 10, 'ExplicitOutputPort', true); - } - if (port != null) { - if (position == 'bottom') { - port.geometry.offset = new mxPoint(-6, 0); - } - if (position == 'right') { - port.geometry.offset = new mxPoint(0, -6); - } - port.ordering = ordering; - } - }; - - function configureStylesheet(graph) { - var req = mxUtils.load('styles/Xcos-style.xml'); - var root = req.getDocumentElement(); - var dec = new mxCodec(root.ownerDocument); - dec.decode(root, graph.stylesheet); - }; - </script> - <!-- - Updates connection points before the routing is called. - --> - <script type="text/javascript"> - // Computes the position of edge to edge connection points. - mxGraphView.prototype.updateFixedTerminalPoint = function(edge, terminal, source, constraint) { - var pt = null; - - if (constraint != null) { - pt = this.graph.getConnectionPoint(terminal, constraint); - } - - if (source) { - edge.sourceSegment = null; - } else { - edge.targetSegment = null; - } - - if (pt == null) { - var s = this.scale; - var tr = this.translate; - var orig = edge.origin; - var geo = this.graph.getCellGeometry(edge.cell); - pt = geo.getTerminalPoint(source); - - // Computes edge-to-edge connection point - if (pt != null) { - pt = new mxPoint(s * (tr.x + pt.x + orig.x), - s * (tr.y + pt.y + orig.y)); - - // Finds nearest segment on edge and computes intersection - if (terminal != null && terminal.absolutePoints != null) { - var seg = mxUtils.findNearestSegment(terminal, pt.x, pt.y); - - // Finds orientation of the segment - var p0 = terminal.absolutePoints[seg]; - var pe = terminal.absolutePoints[seg + 1]; - var horizontal = (p0.x - pe.x == 0); - - // Stores the segment in the edge state - var key = (source) ? 'sourceConstraint' : 'targetConstraint'; - var value = (horizontal) ? 'horizontal' : 'vertical'; - edge.style[key] = value; - - // Keeps the coordinate within the segment bounds - if (horizontal) { - pt.x = p0.x; - pt.y = Math.min(pt.y, Math.max(p0.y, pe.y)); - pt.y = Math.max(pt.y, Math.min(p0.y, pe.y)); - } else { - pt.y = p0.y; - pt.x = Math.min(pt.x, Math.max(p0.x, pe.x)); - pt.x = Math.max(pt.x, Math.min(p0.x, pe.x)); - } - } - } - // Computes constraint connection points on vertices and ports - else if (terminal != null && terminal.cell.geometry.relative) { - pt = new mxPoint(this.getRoutingCenterX(terminal), - this.getRoutingCenterY(terminal)); - } - } - - edge.setAbsoluteTerminalPoint(pt, source); - }; - </script> - - <!-- - Overrides methods to preview and create new edges. - --> - <script type="text/javascript"> - // Sets source terminal point for edge-to-edge connections. - mxConnectionHandler.prototype.createEdgeState = function(me) { - var edge = this.graph.createEdge(); - - if (this.sourceConstraint != null && this.previous != null) { - edge.style = mxConstants.STYLE_EXIT_X + '=' + this.sourceConstraint.point.x + ';' + - mxConstants.STYLE_EXIT_Y + '=' + this.sourceConstraint.point.y + ';'; - } else if (this.graph.model.isEdge(me.getCell())) { - var scale = this.graph.view.scale; - var tr = this.graph.view.translate; - var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x, - this.graph.snap(me.getGraphY() / scale) - tr.y); - edge.geometry.setTerminalPoint(pt, true); - } - - return this.graph.view.createState(edge); - }; - - mxConnectionHandler.prototype.isStopEvent = function(me) { - return me.getState() != null || mxEvent.isRightMouseButton(me.getEvent()); - }; - - // Updates target terminal point for edge-to-edge connections. - mxConnectionHandlerUpdateCurrentState = mxConnectionHandler.prototype.updateCurrentState; - mxConnectionHandler.prototype.updateCurrentState = function(me) { - mxConnectionHandlerUpdateCurrentState.apply(this, arguments); - - if (this.edgeState != null) { - this.edgeState.cell.geometry.setTerminalPoint(null, false); - - if (this.shape != null && this.currentState != null && - this.currentState.view.graph.model.isEdge(this.currentState.cell)) { - var scale = this.graph.view.scale; - var tr = this.graph.view.translate; - var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x, - this.graph.snap(me.getGraphY() / scale) - tr.y); - this.edgeState.cell.geometry.setTerminalPoint(pt, false); - } - } - }; - - // Updates the terminal and control points in the cloned preview. - mxEdgeSegmentHandler.prototype.clonePreviewState = function(point, terminal) { - var clone = mxEdgeHandler.prototype.clonePreviewState.apply(this, arguments); - clone.cell = clone.cell.clone(); - - if (this.isSource || this.isTarget) { - clone.cell.geometry = clone.cell.geometry.clone(); - - // Sets the terminal point of an edge if we're moving one of the endpoints - if (this.graph.getModel().isEdge(clone.cell)) { - clone.cell.geometry.setTerminalPoint(point, this.isSource); - } else { - clone.cell.geometry.setTerminalPoint(null, this.isSource); - } - } - - return clone; - }; - - var mxEdgeHandlerConnect = mxEdgeHandler.prototype.connect; - mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me) { - var result = null; - var model = this.graph.getModel(); - var parent = model.getParent(edge); - - model.beginUpdate(); - try { - result = mxEdgeHandlerConnect.apply(this, arguments); - var geo = model.getGeometry(result); - - if (geo != null) { - geo = geo.clone(); - var pt = null; - - if (model.isEdge(terminal)) { - pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1]; - pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x; - pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y; - - var pstate = this.graph.getView().getState( - this.graph.getModel().getParent(edge)); - - if (pstate != null) { - pt.x -= pstate.origin.x; - pt.y -= pstate.origin.y; - } - - pt.x -= this.graph.panDx / this.graph.view.scale; - pt.y -= this.graph.panDy / this.graph.view.scale; - } - - geo.setTerminalPoint(pt, isSource); - model.setGeometry(edge, geo); - } - } finally { - model.endUpdate(); - } - - return result; - }; - </script> - <!-- - Adds in-place highlighting for complete cell area (no hotspot). - --> - <script type="text/javascript"> - mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker; - mxConnectionHandler.prototype.createMarker = function() { - var marker = mxConnectionHandlerCreateMarker.apply(this, arguments); - - // Uses complete area of cell for new connections (no hotspot) - marker.intersects = function(state, evt) { - return true; - }; - - return marker; - }; - - mxEdgeHandlerCreateMarker = mxEdgeHandler.prototype.createMarker; - mxEdgeHandler.prototype.createMarker = function() { - var marker = mxEdgeHandlerCreateMarker.apply(this, arguments); - - // Adds in-place highlighting when reconnecting existing edges - marker.highlight.highlight = this.graph.connectionHandler.marker.highlight.highlight; - - return marker; - } - </script> - <!-- - Implements a perpendicular wires connection edge style - --> - <script type="text/javascript"> - mxEdgeStyle.WireConnector = function(state, source, target, hints, result) { - // Creates array of all way- and terminalpoints - var pts = state.absolutePoints; - var horizontal = true; - var hint = null; - - // Gets the initial connection from the source terminal or edge - if (source != null && state.view.graph.model.isEdge(source.cell)) { - horizontal = state.style['sourceConstraint'] == 'horizontal'; - } else if (source != null) { - horizontal = source.style['portConstraint'] != 'vertical'; - - // Checks the direction of the shape and rotates - var direction = source.style[mxConstants.STYLE_DIRECTION]; - - if (direction == 'north' || direction == 'south') { - horizontal = !horizontal; - } - } - - // Adds the first point - var pt = pts[0]; - - if (pt == null && source != null) { - pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source)); - } else if (pt != null) { - pt = pt.clone(); - } - - var first = pt; - - // Adds the waypoints - if (hints != null && hints.length > 0) { - for (var i = 0; i < hints.length; i++) { - horizontal = !horizontal; - hint = state.view.transformControlPoint(state, hints[i]); - - if (horizontal) { - if (pt.y != hint.y) { - pt.y = hint.y; - result.push(pt.clone()); - } - } else if (pt.x != hint.x) { - pt.x = hint.x; - result.push(pt.clone()); - } - } - } else { - hint = pt; - } - - // Adds the last point - pt = pts[pts.length - 1]; - - if (pt == null && target != null) { - pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target)); - } - - if (horizontal) { - if (pt.y != hint.y && first.x != pt.x) { - result.push(new mxPoint(pt.x, hint.y)); - } - } else if (pt.x != hint.x && first.y != pt.y) { - result.push(new mxPoint(hint.x, pt.y)); - } - }; - - mxStyleRegistry.putValue('wireEdgeStyle', mxEdgeStyle.WireConnector); - - // This connector needs an mxEdgeSegmentHandler - mxGraphCreateHandler = mxGraph.prototype.createHandler; - mxGraph.prototype.createHandler = function(state) { - var result = null; - - if (state != null) { - if (this.model.isEdge(state.cell)) { - var style = this.view.getEdgeStyle(state); - - if (style == mxEdgeStyle.WireConnector) { - return new mxEdgeSegmentHandler(state); - } - } - } - - return mxGraphCreateHandler.apply(this, arguments); - }; - </script> - -</head> - -<!-- Page passes the container for the graph to the program --> - -<body onload="main(document.getElementById('graphContainer'), - document.getElementById('outlineContainer'), - document.getElementById('toolbarContainer'), - document.getElementById('sidebarContainer'), - document.getElementById('statusContainer'));" style="margin:0px;"> - - <!-- Creates a container for the splash screen --> - <div id="splash" style="position:absolute;top:0px;left:0px;width:100%;height:100%;background:white;z-index:1;"> - <center id="splash" style="padding-top:230px;"> - <img src="images/loading.gif"> - </center> - </div> - - <!-- Creates a container for the sidebar --> - <div id="toolbarContainer" style="position:absolute;white-space:nowrap;overflow:hidden;top:0px;left:0px;max-height:24px;height:36px;right:0px;padding:6px;background-image:url('images/toolbar_bg.gif');"> - </div> - - <!-- Creates a container for the toolbox --> - <div id="sidebarContainer" class="ui-accordion ui-widget ui-helper-reset" style="position:absolute;overflow:scroll;top:36px;left:0px;bottom:36px;max-width:266px;width:270px;padding-top:10px;padding-left:4px;"> - </div> - - <!-- Creates a container for the graph --> - <div id="graphContainer" style="position:absolute;overflow:hidden;top:36px;left:270px;bottom:36px;right:0px;background-image:url('images/grid.gif');cursor:default;"> - </div> - - <!-- Creates a container for the outline --> - <div id="outlineContainer" style="position:absolute;overflow:hidden;top:36px;right:0px;width:200px;height:140px;background:transparent;border-style:solid;border-color:black;"> - </div> - - <!-- Creates a container for the sidebar --> - <div id="statusContainer" style="text-align:right;position:absolute;overflow:hidden;bottom:0px;left:0px;max-height:24px;height:36px;right:0px;color:white;padding:6px;background-image:url('images/toolbar_bg.gif');"> - <div style="font-size:10pt;float:left;"> - <a href="http://fossee.in/" target="_tab">FOSSEE</a> - </div> - </div> - - <!-- Secret --> - <p class="accordion-expand-holder" style="display:none"> - <a id='toggleBlocks' class="accordion-expand-all">Expand All</a> - </p> - -</body> -<!-- It's good if this part happens after the entire page has loaded--> -<script type="text/javascript"> - // Preload all images - var dir = ["blocks", "images"]; - var fileextension = "."; - var blockImages = []; - $.each(dir, function(index, value) { - $.ajax({ // http://stackoverflow.com/a/18480589 - url: value, - success: function(data) { - $(data).find("a:contains(" + fileextension + ")").each(function() { - var filename = this.href.replace(window.location.host, ""); - filename = filename.replace("https://", value); - filename = filename.replace("http://", value); - blockImages.push(filename); - }); - // Prevent multi-threading and have function within call! - function preload(sources) { - var images = []; - for (var i = 0, length = sources.length; i < length; ++i) { - images[i] = new Image(); - images[i].src = sources[i]; - } - } - preload(blockImages); - } - }); - }); - //Find out more here: http://stackoverflow.com/questions/12843418/jquery-ui-accordion-expand-collapse-all - $(window).load(function() { - var headers = $('#sidebarContainer .accordion-header'); - var contentAreas = $('#sidebarContainer .ui-accordion-content ').hide(); - var expandLink = $('.accordion-expand-all'); - - // add the accordion functionality - headers.click(function() { - var panel = $(this).next(); - var isOpen = panel.is(':visible'); - - // open or close as necessary - panel[isOpen ? 'slideUp' : 'slideDown']() - // trigger the correct custom event - .trigger(isOpen ? 'hide' : 'show'); - - // stop the link from causing a pagescroll - return false; - }); - - // hook up the expand/collapse all - expandLink.click(function() { - var isAllOpen = $(this).data('isAllOpen'); - - contentAreas[isAllOpen ? 'hide' : 'show']() - .trigger(isAllOpen ? 'hide' : 'show'); - }); - - // when panels open or close, check to see if they're all open - contentAreas.on({ - // whenever we open a panel, check to see if they're all open - // if all open, swap the button to collapser - show: function() { - var isAllOpen = !contentAreas.is(':hidden'); - if (isAllOpen) { - expandLink.text('Collapse All') - .data('isAllOpen', true); - } - }, - // whenever we close a panel, check to see if they're all open - // if not all open, swap the button to expander - hide: function() { - var isAllOpen = !contentAreas.is(':hidden'); - if (!isAllOpen) { - expandLink.text('Expand All') - .data('isAllOpen', false); - } - } - }); - }); -</script> - -</html> |