Whenever a data model object is modified, either by the local client or by another collaborator, an event describing the change is fired.
All changes to collaborative objects, such as modifying a string, list, or custom collaborative object, emit events. Because changes can originate from either the local application or a remote collaborator, it is important that applications properly listen for and respond to these events to keep the view in sync with the model.
The type of event that is fired depends on the collaborative object that was
modified and what change was made to it. For example, adding a value to a string
will fire a
TextInsertedEvent.
For details about event types, see the
EventType enum in the API reference.
Event dispatching
Events are dispatched after the completion of the current synchronous block rather than executed immediately. This ensures all changes to the model are applied prior to executing the event handlers. Consider the following example.
var onValueAdded = function(event) {
console.log("Items added", event.values);
};
var list = model.createList();
list.addEventListener(gapi.drive.realtime.EventType.VALUES_ADDED, onValueAdded);
console.log("Adding item 1");
list.push("Hello");
console.log("Adding item 2");
list.push("World");
The console for the current collaborator will show:
Adding item 1
Adding item 2
Items added, ["Hello"]
Items added, ["World"]
Other collaborators may receive these changes intermixed with other changes. To
ensure the events are received together, applications
should mark the boundaries of dependant operations using
Model.beginCompoundOperation()
and
Model.endCompoundOperation().
See Conflict Resolution and Compound Operations for more information on
compound events.
Event bubbling and ObjectChangedEvents
Most events are emitted on the specific object that changed and do not bubble. There is
one exception: the ObjectChangedEvent
is a bubbling event that is additionally emitted for every change. The ObjectChangedEvent is
sent to the object that changed and all of its ancestors. One ObjectChangedEvent is emitted
for every object that changed within a compound operation. The specific changes are described
in the events field.
An ObjectChangedEvent
is not as specific as other events, but can simplify management of event
listeners when using MVC frameworks that have other mechanisms for detecting changes. For
example, an ObjectChangedEvent listener added to the root will be informed whenever any
change is made in any part of the model.
function displayObjectChangedEvent(evt) {
var events = evt.events;
var eventCount = evt.events.length;
for (var i = 0; i < eventCount; i++) {
console.log('Event type: ' + events[i].type);
console.log('Local event: ' + events[i].isLocal);
console.log('User ID: ' + events[i].userId);
console.log('Session ID: ' + events[i].sessionId);
}
}
doc.getModel().getRoot().addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, displayObjectChangedEvent);
All other collaborative events do not bubble through the model. Only listeners that are attached directly to the modified object are executed.
Local vs. remote events
All events include a property
isLocal
which can be used to check if the event originated locally. If your
application is applying local view changes directly, instead of in response to
a collaborative object event, any event handlers should check the source of
the event to avoid applying local changes multiple times.
function filterLocalEvents(evt) {
var isLocal = evt.isLocal;
if (!isLocal) {
console.log("Non-local event.");
//Insert UI update code here.
} else {
console.log("Local event.");
}
}