# GoJS Change Log

We maintain a GitHub Repository, which you can star to follow version updates. We also notify of changes on Twitter.

## GoJS 3.0

GoJS 3.0 brings a number of new features for advanced Diagram control, such as custom routing via Routers and data-bound theming with Themes. We have also rewritten some of the internals to take advantage of modern JavaScript, and rewritten the API to use clearer enumerations. These changes are largely backwards-compatible.

There are a number of other changes, detailed below.

### Changes for 3.0.7

- Added InputEvent.commandKey, which returns a normalized key string based on the InputEvent.key and InputEvent.code. This is convenient to use in CommandHandler.doKeyDown or Tool.doKeyDown and their overrides.
- Fixed keyboard shortcuts for QWERTZ-layout keyboards.

### Changes for 3.0.6

- Added another work-around for Babel transpilation bug.
- Fixed the Robot extension to handle "Delete" key events.
- Fixed GridLayout when GridLayout.alignment is `Position` for Parts that have non-zero GraphObject.margin on the left or top sides. Fixed other built-in Layouts that use LayoutNetworks when Nodes have non-zero GraphObject.margin on the left or top sides.

### Changes for 3.0.5

- Added work-around for Babel transpilation bug.
- Fixed some cases of AvoidsNodes routing within Groups.
- Optimized the built-in AvoidsNodes Router to never start when there are no AvoidsNodes links.
- Fixed ForceDirectedLayout not moving nodes that are ForceDirectedVertex.isFixed.
- Fixed the updating of Diagram.documentBounds when dragging between diagrams.

### Changes for 3.0.4

- Fixed keyboard shortcuts for AZERTY-layout keyboards.
- Added a convenience method overload for GraphObject.trigger that accepts parameters taken by the AnimationTrigger constructor.
- Fixed an error on animations of GraphObject.desiredSize.

### Changes for 3.0.3

- Fixed some Group layouts failing to invalidate link routes.
- Efficiency improvements for AvoidsNodes Routing.

### Changes for 3.0.2

- Fixed some interactions with mouse-over events during animations leading to incorrect Part positions.
- Fixed an issue where Binding.ofModel Bindings could cause problems with the clipboard.
- Removed erroneous `position: absolute` inline CSS from Diagram.makeSVG output elements.
- Fixed some Adornment locations when a Part.locationObjectName is set and there is no Adornment.placeholder.
- LinkLabelRouter will no longer unnecessarily move labels after an initial run.

### Changes for 3.0.1

- Potentially incompatible: We have added InputEvent.code to correspond to `KeyboardEvent.code` CommandHandler.doKeyDown now uses `KeyboardEvent.code` instead of `KeyboardEvent.key` for better cross-language shortcut support. This may lead to incompatibilities if you have code (such as testing code) that sets an InputEvent.key value. You may need to additionally set InputEvent.code. If your code does not modify the value of InputEvent.key anywhere (such as in a tool customization or in a CommandHandler.doKeyDown override), you do not need to do anything.
- Fixed some initial positions when Diagram.autoScale scales initial contents, but a scrollbar is still required.
- Fixed some Iterators returned by GoJS (such as from Node.findLinksInto) returning faulty values from use of `Symbol.iterator`.
- Fixed a bug where large nodes in a ForceDirectedLayout would sometimes overlap.

## Changes for 3.0

### New npm packages

For 3.0, the `gojs` npm package contains only the release libraries, and no extensions, documentation or sample code. The documentation, sample, and extensions code can be downloaded separately, via `npm create gojs-kit@latest`.

### Performance

GoJS 3.0 leverages modern JavaScript and more modern Canvas API features for increased performance. However, this also means dropping support for old browsers such as IE11, and there are a number of minor incompatibilities detailed below.

Diagram rendering is now generally faster, and Diagram heap size has been significantly reduced, especially for large graphs.

### Routers

AvoidsLinks Router

One has always been able to customize the computed paths for Links by setting properties on a Link or on its connected port elements, or by overriding methods on a custom Link subclass. There is now support for a separate routing phase where instances of Router can modify Links. See the intro page on routers for more information.

GoJS 3.0 introduces the AvoidsLinks Router, which attempts to separate parallel link segments, and can work alongside AvoidsNodes routing.

### Theming

GoJS now provides functionality to define and manage themes, and GraphObjects can now be themed via theme bindings. This allows for applications to more easily provide multiple themes, especially light and dark mode. See the intro page in theming for more information.

### Viewport Layers

There are two new default layers in each Diagram, `"ViewportBackground"` and `"ViewportForeground"`. These layers have the new property Layer.isViewportAligned set to `true`. Parts in viewport aligned layers will not obey the Diagram.position or Diagram.scale properties, so as the user scrolls or pans or zooms they will remain fixed in the viewport.

Layers with Layer.isViewportAligned set to `true` will automatically position and scale their Parts to be relative to the viewport, based on the Part's GraphObject.alignment and GraphObject.alignmentFocus values, not on its Part.location or GraphObject.position.

### Enumerations

GoJS now uses Typescript enumerations to represent possible values for many properties. This enables autocompletion in some text editors. Some examples:

- Where one wrote: `new go.Panel({ stretch: go.GraphObject.Fill })`,
  one can now write: `new go.Panel({ stretch: go.Stretch.Fill })`.
- Where one wrote: `new go.RowColumnDefinition({ column: 1, sizing: go.RowColumnDefinition.None })`,
  one can now write: `new go.RowColumnDefinition({ column: 1, sizing: go.Sizing.None })`.
- Where one wrote: `new go.TreeLayout({ alignment: go.TreeLayout.AlignmentStart })`,
  one can now write: `new go.TreeLayout({ alignment: go.TreeAlignment.Start })`.

The original static EnumValue properties have been deprecated in favor of these new enumerations, but continue to exist for compatibility. So, for example: `go.GraphObject.Fill === go.Stretch.Fill`. The never-documented EnumValue class has been removed from the library. The new enum values are numbers.

### Other New Features

- Improved Rounded Rectangles: The commonly used `"RoundedRectangle"` Shape.figure now considers the Shape.parameter2 option to be a bit flag mask that determines which corners to round. 1: top-left, 2: top-right, 4: bottom-right, 8: bottom-left. This makes it easier to round only the bottom or top corners, or a single corner. For compatibility, the default flags value rounds all four corners.
- Added the predefined `"Capsule"` figure, as yet another kind of rounded rectangle. See the Shapes sample for an example.
- Added the predefined `"Borders"` figure, as yet another kind of rectangle where the Shape.parameter1 option is a bit flag mask that determines which sides are drawn. 1: top, 2: right, 4: bottom, 8: left. See the Shapes sample for an example.
- Added methods GraphObject.bindModel, GraphObject.bindObject, and GraphObject.bindTwoWay, as convenience functions for adding a Binding to a GraphObject, which additionally call Binding.ofModel, Binding.ofObject, and Binding.makeTwoWay, respectively. The fourth argument to GraphObject.bind has been deprecated -- if you want a TwoWay Binding, call GraphObject.makeTwoWay, which is a clearer declaration of intent.
- The ForceDirectedLayout class has been rewritten, although the API remains compatible. For small to medium-sized simple graphs (up to around 1000 nodes), these changes should not be noticeable, however for large or complex graphs node placements should be better. Several properties have been added to ForceDirectedLayout -- look for names with "prelayout" in them.
- LayeredDigraphLayout has improved the routing of some links that go "backward" to form a cycle.
- Added static functions Point.stringifyFixed, Size.stringifyFixed, Rect.stringifyFixed, Margin.stringifyFixed, Spot.stringifyFixed, and Geometry.stringifyFixed to produce Binding.backConverters that reduce the size of the output JSON and to make it easier to read and compare. Added the property Model.pointsDigits to control how many decimal digits are written for the Link.points list by Model.toJson.
- Added the static function TextBlock.isValidFont to allow dynamically deciding whether a CSS font string is valid or not. This is like the existing Brush.isValidColor for checking CSS color strings.
- Added the read-only property Node.isTreeRoot as a quick way to decide whether a node is a "root" node, while ignoring links that are not Link.isTreeLink, ignoring reflexive links, and considering Diagram.isTreePathToChildren.
- Code that depends on a Group.placeholder or an Adornment.placeholder now also checks that the placeholder is GraphObject.isVisibleObject, to make it possible to dynamically control whether the placeholder determines the position and size of the Group or Adornment.
- Calls to Model.toIncrementalJson or Model.toIncrementalData no longer signal an error if the model is a GraphLinksModel and GraphLinksModel.linkKeyProperty is the empty string. Instead, it first modifies the model so that GraphLinksModel.linkKeyProperty is set to `"key"`, thereby assigning unique key values to all of the link data objects, before producing the resulting text or data.
- Added the property LinkReshapingTool.resegmentingDistance, to control the distance from a straight line that two adjacent nearly straight segments should be combined into a single segment.
- Group animations such as group expansion and adding members have been improved.

## Changes and Incompatibilities

### Diagram.inherit

The Diagram.inherit static function has been removed from the API. Now the only supported way to define subclasses is to use `class ... extends ... { ... }`.

However, this is still a JavaScript library, so it is still possible to dynamically override an individual method on an individual object just by assigning it to a `function(...) { ... }`. A number of samples continue to demonstrate this by assigning a method on a Tool or on the CommandHandler during Diagram initialization.

### GoJS Set and Map and List

The GoJS Set and Map and List collection classes, and their iterators, now implement the JavaScript `Symbol.iterator` static property. This means that they can be used with `for ... of` statements and spread syntax `[...x]`.

      const s = new go.Set();
      s.add(1); s.add(2); s.add(3);

      for (let x of s.iterator) {
        console.log(x);
      }
      // prints:
      // 1
      // 2
      // 3

      [...s] // returns the array [1, 2, 3]
      [...s.iterator] // also returns the array [1, 2, 3]

However, for compatibility, iterators are otherwise unchanged, and Set.iterator, Map.iterator, and List.iterator return GoJS iterators, not the built-in JS iterators.

GoJS Set and Map used to consider both a string and a number of the same value (e.g. "3.14159" and 3.14159) as the same key. They are now considered different keys. Be sure to always get with the same type of value that you added to the Set or set in the Map.

GoJS Set and Map no longer warn about potential collection modification while iterating over the collection.

### InputEvent.key, InputEvent.code, and InputEvent.commandKey

The value of InputEvent.key now exactly reflects the browser `KeyboardEvent.key` value. If your code does not use the value of InputEvent.key anywhere (such as in a tool customization or in a CommandHandler.doKeyDown override), you do not need to do anything. For some keys, these strings are slightly different. The differences are:

GoJS 2.3 | GoJS 3.0
--- | ---
"Esc" | "Escape"
"Subtract" | "-"
"Add" | "+"
"Add" | "="
"Up" | "ArrowUp"
"Down" | "ArrowDown"
"Right" | "ArrowRight"
"Left" | "ArrowLeft"
"Del" | "Delete"

GoJS 3.0 now reports the InputEvent.key faithfully as 'a' or 'A'. In GoJS 2.3 it uppercased each letter key. Note that GoJS treats both "+" and "=" (formerly "Add") as default commands to increase zoom.

As of GoJS 3.0.7, GoJS uses InputEvent.commandKey to determine if any command shall be invoked by CommandHandler.doKeyDown. This readonly property considers the values of both InputEvent.code and InputEvent.key and normalizes the output to be consistent across keyboard languages. If you are overriding Tool or CommandHandler behavior, considering the value of InputEvent.commandKey rather than InputEvent.code or InputEvent.key will lead to more consistent behavior.

### Minor Incompatibilities

- Diagram.initialDocumentSpot and Diagram.initialViewportSpot have had their default value changed from Spot.TopLeft to Spot.None. As a consequence, when they are set to a non-None Spot, they will take precedence over any Diagram.initialContentAlignment.
- `go.licenseKey`, deprecated when 2.0 was released, has been removed. Set the static property `go.Diagram.licenseKey` instead.
- Some default templates have been updated to be themed by default. If you are using default templates in your diagram, you may need to make some minor adjustments to the default themes to better suit the look and feel of your app. Most notably, the default link template is themed such that links are white when using the default dark theme. If your diagram has a dark mode and uses the default link template, define your own link template or use the new theming functionality of v3.0.
- `"Button"` builders no longer have a "pressed" state. `"ContextMenuButton"`s now have more padding.
- GraphObject.areaBackground, formerly deprecated, has been removed. To get the old behavior, wrap a Panel around the GraphObject and set that Panel's GraphObject.background instead.
- The initial value of Model.copiesKey has changed from true to false. For example, this is useful to prevent nodes copied from a Palette to a Diagram to keep the same key in the target diagram's model that it had in the palette's model. To get the old behavior, set `copiesKey: true` on the model.
- The initial value of CommandHandler.isZoomToFitRestoreEnabled has changed from true to false. This removes the ability for repeated Shift-Z commands to restore the original diagram scale and position. But it means that repeated programmatic calls to CommandHandler.zoomToFit will actually zoom-to-fit. To get the old behavior, set `isZoomToFitRestoreEnabled: true` on the CommandHandler.
- The LayeredDigraphLayout.alignOption property now defaults to the value LayeredDigraphAlign.All. The new align code is usually better and faster than the old pack code, sometimes significantly faster. To get the old behavior, set `alignOption: go.LayeredDigraphAlign.None`.
- Layout.getLayoutBounds now respects each Part's GraphObject.margin, which makes it easier to pretend that nodes are smaller or bigger than they actually are. To get the old behavior, don't set Node.margin or set it to zero. TableLayout has been updated to maintain the original behavior because it has always treated Node.margin differently from all other layouts.
- Setting Layer.isTemporary to true no longer automatically sets Layer.isInDocumentBounds to false. If you have added new temporary Layers and you want Parts in those Layers not to be considered when computing the document bounds, you'll need to set that property to false explicitly.
- We have fixed the behavior of CommandHandler.selectAll not to select Parts/Nodes/Links that are not selectable.
- Bundled AnimationTriggers no longer use the AnimationManager.defaultAnimation. This means that `"Trigger"` is no longer a reason for AnimationManager.canStart. This allows bundled animations to run in parallel with default animations. Bundled animations will no longer raise the `"AnimationStarting"` or `"AnimationFinished"` DiagramEvents.
- Binding.isToModel is no longer settable. Instead, one should call Binding.ofModel.
- LayeredDigraphLayout no longer spreads overlapping link segments apart by default. If you want to regain that functionality, add an AvoidsLinksRouter to your Diagram.routers List.

### Changes to Extensions and Samples

All extensions and samples are now in the `create-gojs-kit` npm package rather than in the `gojs` package. We suggest that you download them by executing `npm create gojs-kit@latest`. However you can continue to download everything from the GoJS GitHub repository or from our web site.

Direct script references to extensions in the `gojs` package will no longer work because that package no longer contains any extensions. However it is possible to refer to them in the `create-gojs-kit` package:

    <script src="https://unpkg.com/create-gojs-kit/dist/extensions/AvoidsLinksRouter.js"></script>

There is now an AvoidsLinksRouter extension that helps reduce overlapping orthogonal link segments for links that are unrelated to each other. It is demonstrated in the AvoidsLinksRouter sample.

There is now an AriaCommandHandler extension. We have added an Accessibility extension sample to demonstrate accessibility in GoJS.

The Themes.js extension offers some suggested theming choices.

We have added the `"ChamferedRectangle"` figure to the Figures.js file, which is just like `"RoundedRectangle"`, except the corners are cut off straight at 45 degrees no matter the aspect ratio of the shape. Shape.parameter1 controls the length of both sides of the cut-off triangle. Shape.parameter2 controls which corners are cut off. 1: top-left, 2: top-right, 4: bottom-right, 8: bottom-left.

The extensions Figures.js file no longer redefines the built-in figures.

We have added new samples:

- Warehouse
- Industrial Diagram

We have deleted the `extensionsTS` subdirectory. The `extensionsJSM` subdirectory includes .TS TypeScript files for all of the extensions, along with the compiled .JS JavaScript files that can be loaded as ECMAScript modules.

The JavaScript files in the `extensions` subdirectory are now all generated from the compiled TypeScript files in `extensionsJSM`, which reduces the potential variation in functionality between the two extensions directories.

We have deleted the `RoundedRectangles.js` file from the extensions and extensionsJSM directories. The figures that had been defined there are now predefined in the GoJS library.

The sample HTML pages in both `extensions` and `extensionsJSM` have been moved to the `samples` subdirectory, thereby removing duplicate samples.

A few samples have been moved from the `projects` subdirectory into the `samples` subdirectory. The `projects` subdirectory has been deleted.

We have deleted the Storage extensions. If you need them, copy the code from version 2.

### Fixes

- Moving a collection of Parts no longer invalidates the Link routes in the collection.
- Scrollbars no longer flicker on completion of initial animation.
- Reduced possible duplicate LayoutCompleted events in diagrams with multiple Group layouts.

### Old Change Logs

#### Change log for 2.3

#### Change log for 2.2

#### Change log for 2.1

#### Change log for 2.0

#### Change log for 1.* (unsupported)