documentationfor yFiles for HTML 2.6

Events

The yFiles Class Framework is complemented by further support that provides convenience functionality around event handling.

Events can be easily subscribed to and unsubscribed from through associated methods for adding and removing listener callbacks. These methods take an event handler function as their parameter.

For example, the QueryItemToolTip event of class GraphViewerInputMode can be easily subscribed to and unsubscribed from through the addQueryItemToolTipListener and removeQueryItemToolTipListener method, respectively.

In the yFiles for HTML API documentation, the associated methods to add and remove listener callbacks to events are currently listed along with the corresponding event.

By means of the delegate factory method, appropriate event handler functions can be conveniently registered as implicit closures. The delegate method wraps a given function together with a target object which serves as the caller context for when the given function actually gets invoked. See below for the detailed delegate documentation.

The following code snippet shows how an event handler function is registered as a closure with the current this context:

Adding and removing an event listener ECMAScript Level 5 style
var graphViewerInputMode = new GraphViewerInputMode()

graphViewerInputMode.addQueryItemToolTipListener(
    delegate(this.$onQueryItemToolTip, this)
)

//... and later

graphViewerInputMode.removeQueryItemToolTipListener(delegate(this.$onQueryItemToolTip, this))
Registering an event listener ES2015 style
const graphViewerInputMode = new GraphViewerInputMode()

graphViewerInputMode.addQueryItemToolTipListener((source, evt) => this.$onQueryItemToolTip(source, evt))

When, in response to the QueryItemToolTip event, the $onQueryItemToolTip listener callback gets invoked, all uses of this within the callback’s body actually access the object that the this referenced at invocation time of the delegate factory method.

Delegates

The delegate function wraps one or more JavaScript Function`s and allows to assign an execution context that will be used as `this parameter during the invocation. It works similar as the native EcmaScript bind function.

The advantage of using delegate over Ecmascript’s bind function is that although both implementations will yield fresh instances every time they are called, delegate adds an equals functionality to the function that will be used during event registration and de-registration.Thus the same construct can be used for removing the event subscription to successfully remove a previously added event listener.Using bind would not work in this case because these are two different instances which cannot be checked for identity, and the remove operation would become a no-op.

In addition to adding an execution context to a function, delegates can be combined with the delegate.combine and delegate.remove functions:

Delegate Functions
Function Description
delegate(fun, context)Creates and returns a delegate Function that wraps Functionfun such that during invocation context is bound to the this argument, similarly to the built-in JavaScript bind functionality. The resulting delegate function has an extra equals method that is used when calling the delegate.remove function.
delegate.combine(fun1, fun2)Creates and returns a delegate Function that combines Function`s `fun1 and fun2 to a combined delegate that, when called, will call the passed functions one after another and return the return value of fun2.
delegate.remove(fun1, fun2)Creates and returns a delegate Function that consists of the delegate fun1 with the first occurrence of fun2 removed from it. Will use the equals method of delegates for comparison that was added with the delegate binding function.
delegate.removeAll(fun1, fun2)Like delegate.remove but will return a delegate Function with all occurrences of fun2 removed from fun1.

The delegate.combine and delegate.remove functions can be used to conveniently define own events.

Using delegate utility functions to define and use an event listener in TypeScript
type EventListener<TEvent> = (src: any, args: TEvent) => void

type MyEventType = EventListener<EventArgs>

class MyEventSource {
  private event: MyEventType | null = null

  addItemEventListener(listener: MyEventType): void {
    this.event = delegate.combine(this.event, listener)
  }

  removeItemEventListener(listener: MyEventType): void {
    this.event = delegate.remove(this.event, listener)
  }

  onItemEvent(arg: EventArgs): void {
    if (this.event) {
      this.event(this, arg)
    }
  }
}

class Test {
  itemEventListener(src: any, args: EventArgs) {
    console.log('fired!')
  }
}

const test = new Test()
const eventSource = new MyEventSource()

eventSource.addItemEventListener(delegate(test.itemEventListener, test))
eventSource.onItemEvent(new EventArgs()) // "fired!"
eventSource.removeItemEventListener(delegate(test.itemEventListener, test))
eventSource.onItemEvent(new EventArgs()) // nothing
Using delegate utility functions to define and use an event listener in JavaScript
/**
 * @typedef {function(src: Object, args: EventArgs): void} MyEventType
 */

class MyEventSource {
  constructor() {
    this.event = null
  }

  /**
   * @param {!MyEventType} listener
   */
  addItemEventListener(listener) {
    this.event = delegate.combine(this.event, listener)
  }

  /**
   * @param {!MyEventType} listener
   */
  removeItemEventListener(listener) {
    this.event = delegate.remove(this.event, listener)
  }

  /**
   * @param {!EventArgs} arg
   */
  onItemEvent(arg) {
    if (this.event) {
      this.event(this, arg)
    }
  }
}

class Test {
  /**
   * @param {!EventArgs} args
   */
  itemEventListener(src, args) {
    console.log('fired!')
  }
}

const test = new Test()
const eventSource = new MyEventSource()

eventSource.addItemEventListener(delegate(test.itemEventListener, test))
eventSource.onItemEvent(new EventArgs()) // "fired!"
eventSource.removeItemEventListener(delegate(test.itemEventListener, test))
eventSource.onItemEvent(new EventArgs()) // nothing