Intro

Breaking changes are changes to the behaviour of an existing object, function, event, option, parameter or value in the API.

Some changes are minor enhancements that shouldn't adversely affect your code. In exceptional circumstances, we may make changes to behaviours in your existing implementation. The details below will help you make the necessary code changes.

Note: New API features that don't affect existing code are not breaking changes. They're described in Release Notes as Enhancements.

8.0.0

Changes to defaults

  • In previous versions, labels were drawn over glyphs by default. From 8.0, glyphs are now drawn over labels by default because this ordering is generally better when using both labels and glyphs for styling. To keep the order as before, with labels drawn over glyphs, set the legacyGlyphAndLabelOrdering option to true.
  • The existing straighten option has now also been added to chart.combo().arrange(), to improve the consistency between layout and arrangement behaviour. It's true by default, meaning that combo arrangements now also have link offsets reset by default. To keep link offset behaviour unchanged, set straighten to false.

Changes to bundled resources

The KeyLines bundle has been streamlined, and third-party resources have been removed. Specifically, the css, map, and pdf directories, along with some redundant files from the images and fonts directories have been removed.

Any required files are listed, with links, in the Leaflet Integration and PDF Export documentation sections, and can also still be accessed in the 7.8.1 Long Term Availability (LTA) release (or earlier).

Changes to item validation

In previous versions, it was possible to create a link which had id1 and id2 specified, but omitted type: 'link' in its definition. This link looked the same as regular links but didn't respond correctly to some user interactions.

From 8.0, we've improved validation of items and this is no longer possible. To create a link, you must always set id1, id2 and type: 'link'.

7.0.0

Changing default layout from 'standard' to 'organic'

In previous versions, the default layout that was applied when running chart.layout() or chart.expand() was 'standard'.

From 7.0, the default layout is now organic as it is our most advanced force-directed layout.

Chart.expand() API

The packing: 'adaptive', which is the default packing when running chart.expand(), now behaves differently when the function is run with a default layout.

This is because the default layout has changed from 'standard' to 'organic' and the packing behaviour is different for the two layouts:

  • standard - 'adaptive' option keeps items fixed except for the items immediately neighbouring the new nodes
  • organic - 'adaptive' option may move more items in the chart, but movements are as small as possible

If you want to use the default organic layout with a packing behaviour similar to the previous behaviour, specify fix: 'nonadjacent' in the options object.

Alternatively, if you want to continue using the standard layout and keep the previous packing behaviour, you can set the layout explicitly to 'standard' when running chart.expand().

Chart.layout() API

The default packing option for chart.layout() is now 'circle'. To restore the previous behaviour, specify packing: 'rectangle' in the options object.

KeyLines no longer cloning the d property

In previous versions, KeyLines would deep clone the d property value every time the property was imported to the chart model or retrieved from it:

// the d property on node 'a' is set and its value is cloned
var d = { value: 1 };
chart.setProperties({ id: 'a', d });
d.value = 2;
console.info(chart.getItem('a').d.value); // 1

From 7.0, KeyLines no longer clones the object and the data inside the d property is instead retained on the node:

// the d property on node 'a' is set and its value is not cloned
var d = { value: 1 };
chart.setProperties({ id: 'a', d });
d.value = 2;
console.info(chart.getItem('a').d.value); // 2

This new behaviour, which improves performance and memory usage, affects the following KeyLines functions that can accept or retrieve d properties: chart.animateProperties(), chart.createLink(), chart.each(), chart.expand(), chart.filter(), chart.foreground(), chart.getItem(), chart.load(), chart.merge(), chart.serialize(), chart.setItem(), chart.setProperties().

To restore the previous behaviour, deep clone the object containing the d property before passing it to KeyLines.

Removing callbacks from public API

In previous versions, asynchronous functions could either provide a callback parameter or return a promise.

From 7.0, async functions are promisified by default to align with modern standards. As a result, we've removed KeyLines.promisify() from the API, Typescript and documentation.

If you are already using KeyLines with promises, you don't need to change your code. You can, however, remove your call to KeyLines.promisify() as it has no effect. If you are using KeyLines with TypeScript, you need to remove KeyLines.promisify() as you will see a build error that the function has been removed from the type definitions.

See our Asynchronous JavaScript documentation for more details about promises.

How to continue using KeyLines with callbacks

The KeyLines.callbacks() function can be used to continue using KeyLines with callbacks. This wrapper function returns a KeyLines object that works with both callbacks and promises so that you can easily gradually update your code to use promises. We recommend migrating to promises as soon as possible.

See the Using KeyLines with callbacks documentation for more details.

Note that the following breaking changes were introduced in 7.0 for callback users:

  • Previously, some errors from KeyLines could be handled synchronously in a try/catch statement. From 7.0, synchronous error handling is no longer available for asynchronous functions. If you want to add special error handling when using callbacks, you should listen for unhandled exceptions instead:

    //  browser
    window.addEventListener('error', function(err) {
      // do something with the error
      // the error may still be shown in the console depending on the browser
    });
    //  Node and Modern JS
    process.on('uncaughtException', (err)=> {
      // do something with the error
    });
  • Previously, using asynchronous getter/setter functions as a setter also returned the current value. From 7.0, setters no longer return the value. To retrieve it, call the getter:

    chart.options({ minZoom: 0.01 });
    const currentOptions = chart.options();

Removing shape nodes from public API

In previous versions, shape nodes were a special node type with w and h (width and height) set that was drawn in the chart background under regular nodes and links.

In 7.0, we've removed shape nodes from the public API as they have been superseded by more modern rectangular combos and rectangular nodes. If your code previously contained shape nodes with w and h set, these nodes will now be drawn as rectangular nodes in the node layer.

If you want to continue using shape nodes, you need to:

  • make sure your nodes have w and h set
  • set the legacyShapeNodeBehaviour option to true
  • if you're using Typescript, replace your shape TypeScript definition with node TypeScript definition

Note that it's not possible to use both legacy shape nodes and regular rectangular nodes simultaneously in your chart.

6.0.0

Expand API

From 6.0, the default expand behaviour has been changed to make use of the adaptive layout features released in 5.10. Calling expand() with default options will now only make changes to your chart that are needed to adapt to the incoming changes. The exact changes in defaults are:

  • default options: The default options when specifying a layout are now the same as when supplying no arguments.
  • packing option: The default for the packing option for the expand() API is now 'adaptive'. To restore the previous behaviour, specify packing: 'rectangle' in the expand options object.
  • tidy option: The default for the tidy option for the expand() API is now true. Note that tidy is deprecated. Use the packing option instead. To restore the previous behaviour, specify tidy: false in the expand options object.
  • fix option: The default for the fix option for the expand() API is now 'adaptive'. To restore the previous behaviour, specify fix: 'nonadjacent' in the expand options object.
  • consistent option: The default for the consistent option is now true. To restore the previous behaviour, specify consistent: false in the expand options object.
  • image loading: The expand() API no longer waits for images to load.

getItemInfoAt API

  • return value: The returned subItemInfo property has been replaced by subItem, which returns the same value.

Chart Functions

  • The createLink() function can now only be called when the pointer is down on the chart, and should therefore be typically called from within a drag-start event handler as intended.

For users of the bind() events engine, it should be called from within a mousedown event handler.

Chart Options

  • The default for the link dragging option is now false. To restore the previous behaviour, specify drag: { links: true }.
  • The default for the adaptiveStyling option is now true. To restore the previous behaviour, specify zoom: { adaptiveStyling: false }.

Chart Events

Some events used with the bind() API have modified behaviour. Most of these are enhancements. Consider migrating to the on() API instead.

  • Ctrl + Click on MacOS now fires the 'context-menu' event instead of the 'click' event.

  • Selection is now updated after a click instead of a pointer-down / mousedown event.

To prevent default selection, use the selection-change / selectionchange event.

  • Dragging items no longer selects them by default, which allows you to drag items without losing your selection. As a result: ul li chart.selection() will not always give you the list of dragged items. When dragging items with the bind() API, check whether the id is selected.
    chart.bind('dragstart', function (type, id) {
      const selection = chart.selection();
      const idsBeingDragged = selection.includes(id) ? selection : [id];
      // etc
    });
  • Dragged items will not always be drawn over other chart items unless they are also selected.

5.0.0

Map mode

  • drag-start returns: The drag-start event now always returns a 'hand' type when dragging on the map in map mode, where previously it could return ‘move’ even though nodes cannot be dragged.
  • Leaflet version support: Map mode requires Leaflet version 1.3.4, which is included in the KeyLines download. Earlier versions of Leaflet aren't supported, and later versions will trigger console warnings.
  • Map tile wrapping: By default, map tiles wrap around the world, so you'll see Asia to the west of America if you zoom out far enough. To restore the previous behaviour, specify noWrap: true in the tiles map options settings.
  • toDataURL image exports: If you use chart.toDataURL to export an image of the chart, the width and height parameters are ignored. To get different sized images, use KeyLines.setSize before calling toDataURL, and then reset to the previous size. To mask the underlying transition and let your users know that an export is running in the background, you may want to add a loading "spinner".
  • viewchange events: When in map mode, multiple view-change events are now no longer fired during a pan of the map. Instead a single ‘view-change’ event is fired at the end of the drag.

Assets

  • Asset images: These are now embedded in KeyLines, so you no longer have to add the KeyLines assets folder to your projects. The 'assets' option in KeyLines.paths() no longer has any effect. To replace the navigation controls with your own custom images, turn off navigation controls and add your own controls as elements in your page. For an example, see the Social Network Analysis demo.
  • Missing images: It's no longer possible to overwrite the 'missing images' icon. To display your own icon for missing images, replace them before they're added to KeyLines.
  • Cursor support in IE11 and Microsoft Edge: IE11 and Edge don't support embedded cursors. If you hover over a node, the default pointer will show as the mouse icon instead of the KeyLines 'openhand' cursor.

Image loading

Unlike previous versions, KeyLines 5.0 loads images asynchronously, so images are added to the chart as soon as they're available.

Asynchronous functions that load image data into the chart, such as chart.load() and chart.setProperties(), are returned before image loading is complete Their callbacks/promises are resolved once images are loaded. See Asynchronous JavaScript for more details.

Using images from different domains in HTML5 Canvas

In most cases, you couldn't view insecure images from different domains in earlier KeyLines versions due to CORS security restrictions. One exception was images shown in KeyLines Canvas mode. These could be rendered but not exported or cut out into circular shapes.

In KeyLines 5.0 and later, all insecure images will be marked as missing. This means KeyLines will be consistently clear about which images can be exported. For details of how to make sure all images are secure, see Cross-Origin Images (CORS).

One effect of this is that if you download demos from this site and run them directly from the file system, you'll no longer see any images in the chart. We always recommend serving downloaded demos from a web server instead of the file system.

chart.toDataURL

  • Default size: In previous versions, the default size for the image created by chart.toDataURL was 100x100 pixels if no width and height were specified. The default size is now the size of the chart element.
  • Callback values: We've removed an undocumented, legacy return value for this function, so you should check to make sure you're using the value returned by the callback. For more information, see Asynchronous JavaScript.
  • fit option: The default fit option has changed from 'view' to 'exact'.

chart.setProperties

chart.setProperties() no longer removes properties that are set to null or undefined. If your code previously used 'undefined' to test whether properties existed, you'll now also need to check for values.

chart.setProperties({ id: '1', t: null }, false, function () {
  var item = chart.getItem('1');

  console.log(item.t); // null
  console.log(item.hasOwnProperty('t')); // true
});

Events behaviour

  • selection-change chart event: The selection-change chart event no longer incorrectly fires during clicks on the chart background when nothing was previously selected. If you still need to react to a click on the background, use the click event instead.
  • 'redraw' event: We've removed an undocumented event of type 'redraw'.

Node shape object property options: 'e' and 'w'

Following our deprecation announcement on 15 January 2018, the following node shape (sh) object property options are no longer available or supported:

  • 'e' - east-pointing signpost
  • 'w' - west-pointing signpost

If you want to customise node shapes, use font icons. For examples, see the Style Nodes demo.

Following our deprecation announcement on 15 January 2018, the horizontal links feature is no longer available or supported. As a result, the following link properties have been removed:

  • 'st' - sets a horizontal link style
  • 'y' - sets the position of the central section of the link along the Y-axis in world coordinates

We've also removed the 'fanLength' chart option, previously used to configure horizontal links.

TypeScript definition updates

We've taken the properties 'glyphs' and 'transition' (used for the 'linkStyle' chart option) out of the 'LinkStyle' interface and moved them to a new interface 'LinkStyleOptions'.

4.0.0

chart.bind('double-click')

In previous versions, double-clicking a combo had no effect. Now, double-clicking a combo toggles between open and closed states by default.

To prevent this behaviour, bind to the double-click event and return true. Note that to preserve the default behaviour of a double-click on the chart background causing a zoom, you should not return true in the case where the background is clicked. For example:

chart.on('double-click', function ({id}) {
  return id !== null; // return false if the background is double-clicked; true otherwise
});

chart.each

We've added an 'items' option to chart.each. It lets you choose which items to iterate over when using combos. The options are:

  • 'underlying' - iterates over items that are not combo nodes or combo links (default).
  • 'toplevel' - iterates over items, including combos, that are not inside other combos.
  • 'all' - iterates over every item.

To maintain existing behaviour, add items: 'toplevel' to the chart.each options object.

chart.filter and chart.foreground

We've deprecated the 'combos' option on chart.filter and chart.foreground and replaced it with the 'items' option.

To maintain existing behaviour, if you're using:

  • combos: true, replace it with items: 'underlying'
  • combos: false, replace it with items: 'toplevel'

The default option has changed from combos: false, to items: 'underlying'. If you were using the default setting in 3.8 and earlier, you need to explicitly set items: 'toplevel' to avoid a behaviour change.

chart.getItem

chart.getItem now returns items inside combos. Previously, it returned null. To find out whether an item is inside a combo, use chart.combo().find.

chart.hide, chart.removeItem and chart.show

chart.hide, chart.removeItem and chart.show now apply to items inside combos; previously they didn't. To find out whether an item is inside a combo, use chart.combo().find.

chart.layout consistent option

If your current KeyLines version has consistent: true set in chart.layout, you may get a different result the first time you run a layout after upgrading. This is a one-off breaking change: subsequent layouts will be consistent with your first result.

chart.layout('lens'), chart.layout('standard') and chart.layout('structural')

We've improved the following layouts:

  • Lens - it now provides a more dense layout in some cases where nodes used to be thinly distributed.
  • Standard and structural - they're now better at spacing large items that could sometimes overlap.

In structural layout only, we've also improved the way nodes are arranged in individual groups to reduce the chance of them overlapping.

The new layout behaviour improves every use case we support, so there is no option to maintain the existing behaviour.

chart.options(hover)

We've reduced the default hover time in the hover chart option from 1000 to 150 milliseconds. To maintain existing behaviour, call:

chart.options({hover: 1000})

chart.ping

If you call chart.ping on a node inside a closed combo, KeyLines will now ping the first visible parent combo. If you want to maintain existing behaviour and not ping the parent, you must first use chart.combo().find and chart.combo().isCombo to determine whether the node is in a closed combo.

If you use chart.ping to animate a node or link, the animated effect now appears in front of any shapes on the chart. This new ping behaviour improves every use case we support, so there is no option to maintain existing behaviour.

Selected nodes

When users select or drag nodes, they're now always drawn on top of unselected nodes and no longer hidden behind them. This new behaviour improves every use case we support, so there is no option to maintain the existing behaviour.

End of support for IE9 and IE10

Microsoft stopped supporting these older versions back in January 2016. In KeyLines 3.5, we announced our intention to follow their direction. KeyLines support for IE9 and IE10 has now ended.

3.5.0

  • Links - KeyLines now enforces that the id1 and id2 properties on links cannot be changed once a link has been loaded into the chart. To change the nodes that a link points to, you should remove the link and replace it with a new one.
  • Shapes - the ci (cutout circle) property no longer applies to this object type.
  • chart.contains() - hidden nodes in shape objects are now returned.
  • KeyLines.mode() - 'auto' option now defaults to WebGL (if supported).
  • chart.serialize() - we’ve changed the way the items property is serialized for combos when using chart.serialize(). Chart data serialized from an older version of KeyLines will still load correctly in 3.5. If you just use chart.serialize() to save the current chart or to maintain an undo/redo stack, you won’t need to change anything.

However, if your code parses the output from chart.serialize() and you use combos, chart.serialize().items will now include items contained in combos.

To iterate only over items not contained in combos, use chart.each() instead.

3.3.0

  • Time bar: removed longDays and shortDays options.

3.1.0

  • We've changed the way KeyLines handles fonts. Earlier versions used the Ubuntu font family. KeyLines now uses your browser's default sans-serif font, and defers to an external font loader for font icons. If you're using font icons, follow the migration steps described in Font Loading.

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.