The GoEditor Boilerplate is used as a framework to make GoJS Editor Applications that have several standard editor functionalities, like saving / loading, importing / exporting, and dynamic data property editing. It exists in main/projects/goeditor_boilerplate
Every GoEditor application is guaranteed to have:
To build a GoEditor application, first make sure you have Node and npm installed on your machine.
The build function is located at main/projects/goeditor_boilerplate/generateEditor.js
. To run this, in a Command Prompt window at the proper path, simply write node generateEditor.js PATH_TO_CONFIG
, where PATH_TO_CONFIG
is a relative path string (relative to the generateEditor.js
file) to a JSON file that contains info on how to build you specific app.
To build your specific GoEditor application, you must provide several properties in a JSON configuration file. We'll go over each one of these supported properties now.
name
- The name of your application (i.e. "GoTimeline")
fileName
- The name of your application as it appears in a directory (i.e. "gtl")
version
- The version of your application (i.e "1.0")
description
- The description / instructions for you application. This will be placed beneath your application editor interface. This may be a plain string, or an HTML-formatted one.
initFiles
- An Array of JavaScript file paths, relative to main/projects/goeditor_boilerplate/generateEditor.js
, that contain your custom code that must run onload in the init() function. This often includes Diagram configuring, nodeTemplates, linkTemplates, setting up the model, and anything else you want to run as soon as the page loads. Remember, any functions defined in init() may only be referenced within init().
postInitFiles
- An Array of JavaScript file paths, relative to main/projects/goeditor_boilerplate/generateEditor.js
, that contain your custom code that may run onload outside the init() function. This may include functions that must be called at any time, since these functions are outside the init() scope.
A sample configuration file might look like:
{ "fileName": "gtl", "version": "1.0", "name": "GoTimeline", "description": "<p> This editor allows one to build interactive timelines. Right click anywhere in the diagram to add a new Event or Range node. Select an element to edit its properties. </p> <p> Data formatted properly in rows and columns in either <code>.csv</code> or Google Sheet format can be imported using the File menu. A <code>png</code> of the entire timeline may be exported via the File menu. </p> <p> Timeline data can be saved or loaded to or from various cloud storage services via the Open, Remove, Save, and Save As buttons in the File menu. </p>", "initFiles": [ "../../ryanj/gotimeline-init.js" ], "postInitFiles": [ "../../ryanj/gotimeline-postinit.js" ] }
Assuming that configuration file was located in main/ryanj/gtl-config.json
, to build an editor using it, we'd navigate to main/projects/goeditor_boilerplate
in a Command Prompt window, then run
node generateEditor "../../ryanj/gtl-config.json"
If you need to modify the Diagram, you can always reference it using "myDiagram". The Diagram is initialized in some boilerplate code, so you cannot reinitialize it without an error. But you can still modify its properties. Simply do so inline, like myDiagram.layout = $(TreeLayout)
, instead of inside some call to go.GraphObject.make.
Similarly, the Data Inspector instance is created by the boilerplate code. You will probably need to configure the properties it shows / allows one to edit. You actually can reinitialize the Inspector without an error, so if you need to modify what properties the inspector allows to be modified, simply reinstantiate it like so (be sure to use the 'myInspectorDiv' string!):
Ex:
inspector = new Inspector('myInspectorDiv', myDiagram, { properties: { "event": { show: Inspector.showIfPresent }, "start": { type: "date", show: Inspector.showIfPresent }, "end": { type: "date", show: Inspector.showIfPresent }, "date": { type: "date", show: Inspector.showIfPresent }, "description": { type: "textarea", show: Inspector.showIfPresent }, "color": { type: "color", show: Inspector.showIfPresent }, "isPositionedBelow": { type: "checkbox", show: Inspector.showIfPresent } } } );
To facilitate the creation of Nodes, either one at a time or en masse via file import, there are some structures you need to provide data for. When defining these structures, never use the "var" keyword. These structures must be globally accessible.
The first of these structures is an Array called "categories". For each Node category you have that you want to be able to provide import data for, place that category name into this Array. For example, if you have three Node categories, "NodeA", "NodeB", and "NodeC", and you want to support import functionality for "NodeA" and "NodeB" Nodes, your "categories" Array should look like:
categories = ["NodeA", "NodeB"];
The next structure is a bit more complex. It's called "nodeGenerationMap". This structure is a Map. It holds information on how to generate Nodes for your application. Keys for this map are Node category names. Values are JavaScript objects that must contain some specific properties. We'll go over those properties now.
dataProps
- An Array of JavaScript objects denoting the data properties a Node of this category may have. Each object must have a "name" property and a "type" property. "name" values can be any string, as long as it corresponds to a data property of the Node. "type" values may be "string" | "boolean" | "date" | "color" | "number"
predicates
- Optional. An Array of functions. These functions are used whenever a Node is of this category is being created (either one at a time, or via data file import). Each function may take the Node.data of a newly generated Node and, based on that data (or possibly other factors), decide whether or not that Node should actually be created. If the function returns false, the Node is destroyed and never added to the Diagram.
postCreateFunction
- Optional. Some function that is done after a Node of this category is generated. If you must do some checks or cleanup after a Node of this category is generated, do those things here.
defaultNodeData
- Optional. A JavaScript object holding the default data for a Node of this category. If nothing is provided, the Node by default has no data.
A sample nodeGenerationMap entry might look like:
// "Rectangle" category nodes var dp = [ { name: "name", type: "string" }, { name: "date", type: "date" }, { name: "fillColor", type: "color" }, { name: "isSelectionAdorned", type: "boolean" } ]; // Rectangle node predicate(s) var preds = [ function (nodeData) { // only create rectangle node if name is not "Alpha" return nodeData.name != "Alpha"; } ]; // Rectangle node postCreateFunction var pcf = function (node) { myDiagram.layout.doLayout(myDiagram.nodes); // relayout diagram after a rectangle node is created }; // Rectangle node default data var dd = { isSelectionAdorned: true }; nodeGenerationMap.add("Rectangle", { dataProps: dp, predicates: preds, postCreateFunction: pcf, defaultNodeData: dd });