diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..f85c5a3f84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +javascript/dist +.jshintrc +javascript/examples/**/dist diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000000..1ea3126722 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,101 @@ +var path = require("path"), + fs = require("fs"), + parentFolderName = path.basename(path.resolve('..')), + mxClientContent, + deps; + +// To get the dependencies for the project, read the filenames by matching +// mxClient.include([...]) in mxClient.js. This is not perfect, but the list is +// required in mxClient.js for compatibility. +mxClientContent = fs.readFileSync( + path.join(__dirname, "./javascript/src/js/mxClient.js"), + "utf8" +); +deps = mxClientContent.match(/mxClient\.include\([^"']+["'](.*?)["']/gi).map(function (str) { + return "." + str.match(/mxClient\.include\([^"']+["'](.*?)["']/)[1]; +}); +deps = ["./js/mxClient.js"].concat(deps.slice(0)); + +module.exports = function (grunt) { + grunt.initConfig({ + copy: { + main: { + files: [{ + expand: true, + cwd: "./javascript/src", + src: deps, + dest: "./javascript/dist" + }], + options: { + // After each module, add the object to the '__mxOutput' namespace + // E.g. __mxOutput.mxLog, etc. + process: function (content, srcpath) { + var afterContent = "", + moduleName = path.basename(srcpath, ".js"); + + afterContent += "\n__mxOutput." + path.basename(srcpath, ".js") + + " = typeof " + moduleName + " !== 'undefined' ? " + moduleName + " : undefined;\n"; + + return content + afterContent; + } + } + } + }, + concat: { + dist: { + src: deps.map(function (dep) { + return path.join("./javascript/dist", dep); + }), + dest: './javascript/dist/build.js' + }, + options: { + banner: "(function (root, factory) {\n" + + "if (typeof define === 'function' && define.amd) {\n" + + "define([], factory);\n" + + "} else if (typeof module === 'object' && module.exports) {\n" + + "module.exports = factory();\n" + + "} else {\n" + + "root.mxgraph = factory();\n" + + "}\n" + + "}(this, function () {\n" + + "return function (opts) {\n" + + // Opts will be passed into this function, expand them out as if + // they were globals so they can get picked up by the logic in + // mxClient.js. + "for (var name in opts) { this[name] = opts[name]; }\n" + + "var __mxOutput = {};\n", + footer: "return __mxOutput;\n" + + "};\n" + + "}));" + } + }, + webpack: { + examples: { + entry: "./javascript/examples/webpack/src/anchors.js", + output: { + path: "javascript/examples/webpack/dist", + filename: "anchors.js" + } + } + }, + watch: { + javascripts: { + files: "javascript/src/**/*.js", + tasks: ["umdify"], + options: { + interrupt: true + } + } + }, + }); + + require(parentFolderName === "node_modules" ? "load-grunt-parent-tasks" : "load-grunt-tasks")(grunt); + grunt.registerTask("default", [ + "copy", + "concat", + "webpack" + ]); + grunt.registerTask("build", [ + "default" + ]); +}; diff --git a/docs/manual.html b/docs/manual.html index 6b31799b0e..5135c5e391 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -384,6 +384,30 @@

Project structure and build

Table: Project Directory Structure


+

npm

+ +

mxGraph is also available via the npm package manager. To use mxGraph as + a depedency, use npm install:

+ +
npm install mxgraph --save
+ +

The module can be loaded using require(). This returns a + factory function that accepts an object of options. Options such as + mxBasePath must be provided to the factory function, rather + than specified as global variables.

+ +
var mxgraph = require("mxgraph")({
+  mxImageBasePath: "./src/images",
+  mxBasePath: "./src"
+})
+ +

The factory function returns a 'namespace object' that provides access to + all objects of the mxGraph package. For example, the mxEvent + object is available at mxgraph.mxEvent.

+ +
var mxEvent = mxgraph.mxEvent;
+mxEvent.disableContextMenu(container);
+

JavaScript and Web Applications

Web applications, specifically the use of JavaScript to attempt @@ -1652,4 +1676,4 @@

Layering and Filtering


© 2006-2016 by JGraph Ltd. - + \ No newline at end of file diff --git a/javascript/examples/webpack/anchors.html b/javascript/examples/webpack/anchors.html new file mode 100644 index 0000000000..5402a8b776 --- /dev/null +++ b/javascript/examples/webpack/anchors.html @@ -0,0 +1,22 @@ + + + + Anchors example for mxGraph + + + + + + + + +
+
+ + diff --git a/javascript/examples/webpack/src/anchors.js b/javascript/examples/webpack/src/anchors.js new file mode 100644 index 0000000000..e83fd5c035 --- /dev/null +++ b/javascript/examples/webpack/src/anchors.js @@ -0,0 +1,99 @@ +var mxgraph = require("../../../dist/build")({ + mxImageBasePath: "../../src/images", + mxBasePath: "../../src" + }), + mxGraph = mxgraph.mxGraph, + mxShape = mxgraph.mxShape, + mxConnectionConstraint = mxgraph.mxConnectionConstraint, + mxPoint = mxgraph.mxPoint, + mxPolyline = mxgraph.mxPolyline, + mxEvent = mxgraph.mxEvent, + mxRubberband = mxgraph.mxRubberband, + mxCellState = mxgraph.mxCellState; + +window.onload = function () { + // Overridden to define per-shape connection points + mxGraph.prototype.getAllConnectionConstraints = function(terminal, source) + { + if (terminal != null && terminal.shape != null) + { + if (terminal.shape.stencil != null) + { + if (terminal.shape.stencil != null) + { + return terminal.shape.stencil.constraints; + } + } + else if (terminal.shape.constraints != null) + { + return terminal.shape.constraints; + } + } + + return null; + }; + + // Defines the default constraints for all shapes + mxShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true), + new mxConnectionConstraint(new mxPoint(0.5, 0), true), + new mxConnectionConstraint(new mxPoint(0.75, 0), true), + new mxConnectionConstraint(new mxPoint(0, 0.25), true), + new mxConnectionConstraint(new mxPoint(0, 0.5), true), + new mxConnectionConstraint(new mxPoint(0, 0.75), true), + new mxConnectionConstraint(new mxPoint(1, 0.25), true), + new mxConnectionConstraint(new mxPoint(1, 0.5), true), + new mxConnectionConstraint(new mxPoint(1, 0.75), true), + new mxConnectionConstraint(new mxPoint(0.25, 1), true), + new mxConnectionConstraint(new mxPoint(0.5, 1), true), + new mxConnectionConstraint(new mxPoint(0.75, 1), true)]; + + // Edges have no connection points + mxPolyline.prototype.constraints = null; + + // Program starts here. Creates a sample graph in the + // DOM node with the specified ID. This function is invoked + // from the onLoad event handler of the document (see below). + function main(container) + { + // Disables the built-in context menu + mxEvent.disableContextMenu(container); + + // Creates the graph inside the given container + var graph = new mxGraph(container); + graph.setConnectable(true); + + // Enables connect preview for the default edge style + graph.connectionHandler.createEdgeState = function(me) + { + var edge = graph.createEdge(null, null, null, null, null); + + return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge)); + }; + + // Specifies the default edge style + graph.getStylesheet().getDefaultEdgeStyle()['edgeStyle'] = 'orthogonalEdgeStyle'; + + // Enables rubberband selection + new mxRubberband(graph); + + // Gets the default parent for inserting new cells. This + // is normally the first child of the root (ie. layer 0). + var parent = graph.getDefaultParent(); + + // Adds cells to the model in a single step + graph.getModel().beginUpdate(); + try + { + var v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); + var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30); + var e1 = graph.insertEdge(parent, null, '', v1, v2); + } + finally + { + // Updates the display + graph.getModel().endUpdate(); + } + }; + + main(document.getElementById('graphContainer')); +}; diff --git a/javascript/src/js/mxClient.js b/javascript/src/js/mxClient.js index 3bb06d2f10..804e5d31b8 100644 --- a/javascript/src/js/mxClient.js +++ b/javascript/src/js/mxClient.js @@ -599,143 +599,147 @@ if (mxClient.IS_VML) } } -mxClient.include(mxClient.basePath+'/js/util/mxLog.js'); -mxClient.include(mxClient.basePath+'/js/util/mxObjectIdentity.js'); -mxClient.include(mxClient.basePath+'/js/util/mxDictionary.js'); -mxClient.include(mxClient.basePath+'/js/util/mxResources.js'); -mxClient.include(mxClient.basePath+'/js/util/mxPoint.js'); -mxClient.include(mxClient.basePath+'/js/util/mxRectangle.js'); -mxClient.include(mxClient.basePath+'/js/util/mxEffects.js'); -mxClient.include(mxClient.basePath+'/js/util/mxUtils.js'); -mxClient.include(mxClient.basePath+'/js/util/mxConstants.js'); -mxClient.include(mxClient.basePath+'/js/util/mxEventObject.js'); -mxClient.include(mxClient.basePath+'/js/util/mxMouseEvent.js'); -mxClient.include(mxClient.basePath+'/js/util/mxEventSource.js'); -mxClient.include(mxClient.basePath+'/js/util/mxEvent.js'); -mxClient.include(mxClient.basePath+'/js/util/mxXmlRequest.js'); -mxClient.include(mxClient.basePath+'/js/util/mxClipboard.js'); -mxClient.include(mxClient.basePath+'/js/util/mxWindow.js'); -mxClient.include(mxClient.basePath+'/js/util/mxForm.js'); -mxClient.include(mxClient.basePath+'/js/util/mxImage.js'); -mxClient.include(mxClient.basePath+'/js/util/mxDivResizer.js'); -mxClient.include(mxClient.basePath+'/js/util/mxDragSource.js'); -mxClient.include(mxClient.basePath+'/js/util/mxToolbar.js'); -mxClient.include(mxClient.basePath+'/js/util/mxUndoableEdit.js'); -mxClient.include(mxClient.basePath+'/js/util/mxUndoManager.js'); -mxClient.include(mxClient.basePath+'/js/util/mxUrlConverter.js'); -mxClient.include(mxClient.basePath+'/js/util/mxPanningManager.js'); -mxClient.include(mxClient.basePath+'/js/util/mxPopupMenu.js'); -mxClient.include(mxClient.basePath+'/js/util/mxAutoSaveManager.js'); -mxClient.include(mxClient.basePath+'/js/util/mxAnimation.js'); -mxClient.include(mxClient.basePath+'/js/util/mxMorphing.js'); -mxClient.include(mxClient.basePath+'/js/util/mxImageBundle.js'); -mxClient.include(mxClient.basePath+'/js/util/mxImageExport.js'); -mxClient.include(mxClient.basePath+'/js/util/mxAbstractCanvas2D.js'); -mxClient.include(mxClient.basePath+'/js/util/mxXmlCanvas2D.js'); -mxClient.include(mxClient.basePath+'/js/util/mxSvgCanvas2D.js'); -mxClient.include(mxClient.basePath+'/js/util/mxVmlCanvas2D.js'); -mxClient.include(mxClient.basePath+'/js/util/mxGuide.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxStencil.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxShape.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxStencilRegistry.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxMarker.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxActor.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxCloud.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxRectangleShape.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxEllipse.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxDoubleEllipse.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxRhombus.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxPolyline.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxArrow.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxArrowConnector.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxText.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxTriangle.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxHexagon.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxLine.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxImageShape.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxLabel.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxCylinder.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxConnector.js'); -mxClient.include(mxClient.basePath+'/js/shape/mxSwimlane.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxGraphLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxStackLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxPartitionLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxCompactTreeLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxRadialTreeLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxFastOrganicLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxCircleLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxParallelEdgeLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxCompositeLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/mxEdgeLabelLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyNode.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyEdge.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyModel.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxSwimlaneModel.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxMinimumCycleRemover.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxCoordinateAssignment.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxSwimlaneOrdering.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/mxHierarchicalLayout.js'); -mxClient.include(mxClient.basePath+'/js/layout/hierarchical/mxSwimlaneLayout.js'); -mxClient.include(mxClient.basePath+'/js/model/mxGraphModel.js'); -mxClient.include(mxClient.basePath+'/js/model/mxCell.js'); -mxClient.include(mxClient.basePath+'/js/model/mxGeometry.js'); -mxClient.include(mxClient.basePath+'/js/model/mxCellPath.js'); -mxClient.include(mxClient.basePath+'/js/view/mxPerimeter.js'); -mxClient.include(mxClient.basePath+'/js/view/mxPrintPreview.js'); -mxClient.include(mxClient.basePath+'/js/view/mxStylesheet.js'); -mxClient.include(mxClient.basePath+'/js/view/mxCellState.js'); -mxClient.include(mxClient.basePath+'/js/view/mxGraphSelectionModel.js'); -mxClient.include(mxClient.basePath+'/js/view/mxCellEditor.js'); -mxClient.include(mxClient.basePath+'/js/view/mxCellRenderer.js'); -mxClient.include(mxClient.basePath+'/js/view/mxEdgeStyle.js'); -mxClient.include(mxClient.basePath+'/js/view/mxStyleRegistry.js'); -mxClient.include(mxClient.basePath+'/js/view/mxGraphView.js'); -mxClient.include(mxClient.basePath+'/js/view/mxGraph.js'); -mxClient.include(mxClient.basePath+'/js/view/mxCellOverlay.js'); -mxClient.include(mxClient.basePath+'/js/view/mxOutline.js'); -mxClient.include(mxClient.basePath+'/js/view/mxMultiplicity.js'); -mxClient.include(mxClient.basePath+'/js/view/mxLayoutManager.js'); -mxClient.include(mxClient.basePath+'/js/view/mxSwimlaneManager.js'); -mxClient.include(mxClient.basePath+'/js/view/mxTemporaryCellStates.js'); -mxClient.include(mxClient.basePath+'/js/view/mxCellStatePreview.js'); -mxClient.include(mxClient.basePath+'/js/view/mxConnectionConstraint.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxGraphHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxPanningHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxPopupMenuHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxCellMarker.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxSelectionCellsHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxConnectionHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxConstraintHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxRubberband.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxHandle.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxVertexHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxEdgeHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxElbowEdgeHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxEdgeSegmentHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxKeyHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxTooltipHandler.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxCellTracker.js'); -mxClient.include(mxClient.basePath+'/js/handler/mxCellHighlight.js'); -mxClient.include(mxClient.basePath+'/js/editor/mxDefaultKeyHandler.js'); -mxClient.include(mxClient.basePath+'/js/editor/mxDefaultPopupMenu.js'); -mxClient.include(mxClient.basePath+'/js/editor/mxDefaultToolbar.js'); -mxClient.include(mxClient.basePath+'/js/editor/mxEditor.js'); -mxClient.include(mxClient.basePath+'/js/io/mxCodecRegistry.js'); -mxClient.include(mxClient.basePath+'/js/io/mxCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxObjectCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxCellCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxModelCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxRootChangeCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxChildChangeCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxTerminalChangeCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxGenericChangeCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxGraphCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxGraphViewCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxStylesheetCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxDefaultKeyHandlerCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxDefaultToolbarCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxDefaultPopupMenuCodec.js'); -mxClient.include(mxClient.basePath+'/js/io/mxEditorCodec.js'); +// If script is loaded via CommonJS, do not write