diff --git a/google-drive-realtime-api/google-drive-realtime-api-tests.ts b/google-drive-realtime-api/google-drive-realtime-api-tests.ts
new file mode 100644
index 000000000..62578f42a
--- /dev/null
+++ b/google-drive-realtime-api/google-drive-realtime-api-tests.ts
@@ -0,0 +1,196 @@
+///
+
+// Don't use this as a reference. Use the examples at
+// https://developers.google.com/google-apps/realtime/
+// To use the Realtime API effectively, I needed to read lots of the
+// (well-written) documentation on the site, and to understand parts of
+// realtime-client-utils.js
+// which you can find in the tutorial section of the project's homepage.
+
+declare var $ : any;
+interface JQuery {
+ [key: string]: any;
+};
+
+type CollabModel = gapi.drive.realtime.Model;
+type CollabDoc = gapi.drive.realtime.Document;
+interface CollaborativeObject extends gapi.drive.realtime.CollaborativeObject {}
+interface CollaborativeList extends gapi.drive.realtime.CollaborativeList {}
+interface CollaborativeMap extends gapi.drive.realtime.CollaborativeMap {}
+interface IndexReference extends gapi.drive.realtime.IndexReference {}
+interface CollaborativeString extends gapi.drive.realtime.CollaborativeString {}
+
+type CListOfCObj = CollaborativeList
+type CObjOrStr = CollaborativeObject | string;
+type CMapOfCObjOrStr = CollaborativeMap;
+
+
+module GRealtime {
+
+
+
+
+ var default_loader_options : rtclient.LoaderOptions = {
+ // Your Application ID from the Google APIs Console.
+ appId: "YOUR_APP_ID",
+
+ // This tells us if need to we automatically create a file after auth.
+ autoCreate: false,
+
+ // Client ID from the console.
+ clientId: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
+
+ // The ID of the button to click to authorize. Must be a DOM element ID.
+ authButtonElementId: 'realtime-authorize-button',
+
+ // The MIME type of newly created Drive Files. By default the application
+ // specific MIME type will be used:
+ // application/vnd.google-apps.drive-sdk.
+ //newFileMimeType: 'text/json',
+ newFileMimeType: 'text',
+ //newFileMimeType: null, // default
+
+ // Function to be called to initialize custom Collaborative Objects types.
+ registerTypes: null, // No action
+
+ defaultTitle: "Default default-doc-title",
+
+ // The rest are only defaults
+ afterAuth: function() : void {
+ console.log("default afterAuth called")
+ },
+
+ initializeModel: function(rtmodel:CollabModel) : void {
+ console.log("default initializeModel called");
+ },
+
+ onFileLoaded : function(rtdoc:CollabDoc) : void {
+ console.log("default onFileLoaded called");
+ }
+
+ };
+
+ export class MyRTLoader {
+ public loader_options : rtclient.LoaderOptions = $.extend({},default_loader_options);
+ private rtloader_client : rtclient.RealtimeLoader;
+
+ // call after setting loader_options appropriately
+ authorize() {
+ this.rtloader_client = new rtclient.RealtimeLoader(this.loader_options);
+ this.rtloader_client.start();
+ }
+
+ createNew(title:string, callback: (file:any) => void) {
+ rtclient.createRealtimeFile(title, null, callback);
+ }
+
+ loadAfterAuth(fileid:string) {
+ // use this as part of your afterAuth callback
+ rtclient.params.fileIds = fileid;
+ this.rtloader_client.load();
+ }
+ }
+
+ export class MyRealtimeDoc {
+ protected rtmodel: CollabModel;
+ protected rtdoc: CollabDoc;
+ private myRTLoader = new GRealtime.MyRTLoader();
+
+ newFile(title: string,
+ initializeModel: (x:CollabModel) => void,
+ onFileLoaded: (x:CollabDoc) => void) : void {
+
+ var _afterAuth = () => {
+ this.myRTLoader.createNew(title, (file:rtclient.DriveAPIFileResource) => {
+ console.log(`\n\nThis is the createNew callback. New file's id: ${file.id}\n\n`);
+ $("#file-id-text-input").val(file.id);
+ this.myRTLoader.loadAfterAuth(file.id)
+ })
+ }
+
+ var _initializeModel = (model:CollabModel) => {
+ console.log("\n\nRTModel initialized for NEW document.\n\n");
+ this.rtmodel = model;
+ if( initializeModel ) {
+ initializeModel(model);
+ }
+ }
+
+ var _onFileLoaded = (doc:CollabDoc) => {
+ console.log("\n\nNEW document loaded.\n\n");
+ this.rtmodel = doc.getModel();
+ this.rtdoc = doc;
+ if( onFileLoaded ) {
+ onFileLoaded(doc);
+ }
+ }
+
+ this.myRTLoader.loader_options.onFileLoaded = _onFileLoaded;
+ this.myRTLoader.loader_options.afterAuth = _afterAuth;
+ this.myRTLoader.loader_options.initializeModel = _initializeModel;
+ this.myRTLoader.authorize();
+ }
+
+ loadExisting(fileid: string,
+ onFileLoaded: (doc:CollabDoc) => void) : void {
+
+ rtclient.params.fileIds = fileid;
+
+ var _onFileLoaded = (doc:CollabDoc) => {
+ console.log("\n\nEXISTING document loaded.\n\n");
+ this.rtdoc = doc;
+ this.rtmodel = doc.getModel();
+ if( onFileLoaded ) {
+ onFileLoaded(doc);
+ }
+ };
+
+ this.myRTLoader.loader_options.onFileLoaded = _onFileLoaded;
+ //this.myRTLoader.loader_options.afterAuth = ...
+ this.myRTLoader.authorize();
+ }
+
+ createString() : CollaborativeString { return this.rtmodel.createString(""); }
+
+ createList() : CollaborativeList { return this.rtmodel.createList(); }
+
+ createMap() : CollaborativeMap { return this.rtmodel.createMap(); }
+
+ addToPersistDocRoot(x:{pdata:any}, key:string) {
+ this.rtmodel.getRoot().set(key,x.pdata);
+ }
+
+ bindString(istring:CollaborativeString, $textinput: JQuery) : gapi.drive.realtime.databinding.Binding {
+ return gapi.drive.realtime.databinding.bindString(
+ istring,
+ $textinput[0] );
+ }
+
+
+ }
+
+ // alternative to RealtimePSDoc.bindString
+ function registerLocalStringChangeListener(
+ x: CollaborativeString,
+ listener_or_callback: (e:Event) => void | EventListener) : void {
+ x.addEventListener(gapi.drive.realtime.EventType.TEXT_INSERTED, listener_or_callback);
+ x.addEventListener(gapi.drive.realtime.EventType.TEXT_DELETED, listener_or_callback);
+ }
+
+}
+
+
+// Next example from https://developers.google.com/google-apps/realtime/model-events
+
+declare var doc : CollabDoc;
+function displayObjectChangedEvent(evt:gapi.drive.realtime.ObjectChangedEvent) {
+ 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);
\ No newline at end of file
diff --git a/google-drive-realtime-api/google-drive-realtime-api.d.ts b/google-drive-realtime-api/google-drive-realtime-api.d.ts
new file mode 100644
index 000000000..95f239a34
--- /dev/null
+++ b/google-drive-realtime-api/google-drive-realtime-api.d.ts
@@ -0,0 +1,610 @@
+// Type definitions for Google Realtime API
+// Project: https://developers.google.com/google-apps/realtime/
+// Definitions by: Dustin Wehr
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+// This definition file is merge-compatible with ../gapi/gapi.d.ts
+
+// Note the occurrences of "INCOMPLETE". For some interfaces and object types, I have only included
+// the properties and methods that I've actually used so-far, and will add more as they become useful to me.
+// Or, maybe you want to complete them?
+
+// For Typescript newbs: To get shorter names, use e.g.
+// type CollabModel = gapi.drive.realtime.Model;
+// interface CollabList extends gapi.drive.realtime.CollaborativeList {}
+// See section "Type Aliases" of http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf
+
+// gapi is a global var introduced by https://apis.google.com/js/api.js
+declare module gapi.drive.realtime {
+
+ type GoogEventHandler = ((evt:ObjectChangedEvent) => void) | ((e:Event) => void) | EventListener;
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.Collaborator
+ export class Collaborator {
+ // The HTML color associated with this collaborator. When possible, collaborators are assigned unique colors.
+ color : string;
+
+ // The display name for this collaborator.
+ displayName : string;
+
+ // True if this collaborator is anonymous, false otherwise.
+ isAnonymous : boolean
+
+ // True if this collaborator is the local user, false otherwise.
+ isMe : boolean;
+
+ // The permission ID for this collaborator. This ID is stable for a given user and is compatible with the
+ // Drive API permissions APIs. Use the userId property for all other uses.
+ permissionId : string;
+
+ // A URL that points to the profile photo for this collaborator, or to a generic profile photo for
+ // anonymous collaborators.
+ photoUrl : string;
+
+ // The session ID for this collaborator. A single user may have multiple sessions if they have the same document
+ // open on multiple devices or in multiple browser tabs.
+ sessionId : string;
+
+ // The user ID for this collaborator. This ID is stable for a given user and is compatible with most Google APIs
+ // except the Drive API permission APIs. For an ID which is compatible with the Drive API permission APIs,
+ // use the permissionId property.
+ userId : string;
+
+ new (sessionId:string, userId:string, displayName:string, color:string, isMe:boolean, isAnonymous:boolean,
+ photoUrl:string, permissionId:string) : Collaborator;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.CollaborativeObject
+ export class CollaborativeObject {
+ // The id of this collaborative object. Read-only.
+ id:string;
+
+ // The type of this collaborative object. For standard collaborative objects,
+ // see gapi.drive.realtime.CollaborrativeType for possible values; for custom collaborative objects, this value is
+ // application-defined.
+ // Addition: the possible values for standard objects are EditableString, List, and Map.
+ type:string;
+
+ // Adds an event listener to the event target. The same handler can only be added once per the type.
+ // Even if you add the same handler multiple times using the same type then it will only be called once
+ // when the event is dispatched.
+ addEventListener(type:string, listener:GoogEventHandler, opt_capture?:boolean):void;
+
+ // Removes all event listeners from this object.
+ removeAllEventListeners():void;
+
+ // Removes an event listener from the event target. The handler must be the same object as the one added.
+ // If the handler has not been added then nothing is done.
+ removeEventListener(type:string, listener:GoogEventHandler, opt_capture?:boolean):void;
+
+ // Returns a string representation of this collaborative object.
+ toString():string;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.IndexReference
+ export class IndexReference extends CollaborativeObject {
+ // (Categories of) the shift behavior of an index reference when the element it points at is deleted.
+ static DeleteMode:{
+ SHIFT_AFTER_DELETE: string
+ SHIFT_BEFORE_DELETE: string
+ SHIFT_TO_INVALID: string
+ };
+
+ //The index of the current location the reference points to. Write to this property to change the referenced index.
+ index:number;
+
+ // The behavior of this index reference when the element it points at is deleted.
+ // @return one of the elements of DeleteMode
+ deleteMode():string;
+
+ // The object this reference points to. Read-only.
+ referencedObject():V;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.CollaborativeMap
+ export class CollaborativeMap extends CollaborativeObject {
+ size:string;
+
+ static type:string; // equals "Map"
+
+ // Removes all entries.
+ clear():void;
+
+ // Removes the entry for the given key (if such an entry exists).
+ // @return the value that was mapped to this key, or null if there was no existing value.
+ delete(key:string):V;
+
+ // Returns the value mapped to the given key.
+ get(key:string):V;
+
+ // Checks if this map contains an entry for the given key.
+ has(key:string):boolean;
+
+ // Returns whether this map is empty.
+ isEmpty():boolean;
+
+ // Returns an array containing a copy of the items in this map. Modifications to the returned array do
+ // not modify this collaborative map.
+ // @return non-null Array of Arrays, where the inner arrays are tupples [string, V]
+ items():[string,V][];
+
+ // Returns an array containing a copy of the keys in this map. Modifications to the returned array
+ // do not modify this collaborative map.
+ keys():string[];
+
+ // Put the value into the map with the given key, overwriting an existing value for that key.
+ // @return the old map value, if any, that used to be mapped to the given key.
+ set(key:string, value:V):V;
+
+ // Returns an array containing a copy of the values in this map. Modifications to the returned array
+ // do not modify this collaborative map.
+ values():V[];
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.CollaborativeString
+ export class CollaborativeString extends CollaborativeObject {
+ // The length of the string. Read only.
+ length:number;
+
+ // The text of this collaborative string. Reading from this property is equivalent to calling getText(). Writing to this property is equivalent to calling setText().
+ text:string;
+
+ static type:string; // equals "EditableString"
+
+ // Appends a string to the end of this one.
+ append(text:string):void;
+
+ // Gets a string representation of the collaborative string.
+ getText():string;
+
+ // Inserts a string into the collaborative string at a specific index.
+ insertString(index:number, text:string):void;
+
+ // Creates an IndexReference at the given {@code index}. If {@code canBeDeleted} is set, then a delete
+ // over the index will delete the reference. Otherwise the reference will shift to the beginning of the deleted range.
+ registerReference(index:number, canBeDeleted:boolean):IndexReference;
+
+ // Deletes the text between startIndex (inclusive) and endIndex (exclusive).
+ removeRange(startIndex:number, endIndex:number):void;
+
+ // Sets the contents of this collaborative string. Note that this method performs a text diff between the
+ // current string contents and the new contents so that the string will be modified using the minimum number
+ // of text inserts and deletes possible to change the current contents to the newly-specified contents.
+ setText(text:string):void;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.CollaborativeList
+ export class CollaborativeList extends CollaborativeObject {
+ // The number of entries in the list. Assign to this field to reduce the size of the list.
+ // Note that the length given must be less than or equal to the current size.
+ // The length of a list cannot be extended in this way.
+ length:number;
+
+ static type:string; // equals "List"
+
+ // Returns a copy of the contents of this collaborative list as an array.
+ // Changes to the returned object will not affect the original collaborative list.
+ asArray():V[];
+
+ // Removes all values from the list.
+ clear():void;
+
+ // Gets the value at the given index.
+ get(ind:number):V;
+
+ //Returns the first index of the given value, or -1 if it cannot be found.
+ indexOf(value:V, opt_comparatorFn?:(x1:V, x2:V) => boolean):number;
+
+ //Inserts an item into the list at a given index.
+ insert(index:number, value:V):void;
+
+ // Inserts a list of items into the list at a given index.
+ insertAll(index:number, values:V[]):void;
+
+ // Returns the last index of the given value, or -1 if it cannot be found.
+ lastIndexOf(value:V, opt_comparatorFn?:(x1:V, x2:V) => boolean):number;
+
+ //Moves a single element in this list (at index) to immediately before destinationIndex.
+ //Both indices are with respect to the position of elements before the move.
+ //For example, given the list: ['A', 'B', 'C']
+ //move(0, 0) is a no-op
+ //move(0, 1) is a no-op
+ //move(0, 2) yields ['B', 'A', 'C'] ('A' is moved to immediately before 'C')
+ //move(0, 3) yields ['B', 'C', 'A'] ('A' is moved to immediately before an imaginary element after the list end)
+ //move(1, 0) yields ['B', 'A', 'C'] ('B' is moved to immediately before 'A')
+ //move(1, 1) is a no-op
+ //move(1, 2) is a no-op
+ //move(1, 3) yields ['A', 'C', 'B'] ('B' is moved to immediately before an imaginary element after the list end)
+ move(index:number, destinationIndex:number):void;
+
+ // Moves a single element in this list (at index) to immediately before destinationIndex in the list destination.
+ // Both indices are with respect to the position of elements before the move.
+ // If the provided destination is this list, this function is identical to move(index, destinationIndex).
+ moveToList(index:number, destination:CollaborativeList, destinationIndex:number):void;
+
+ // Adds an item to the end of the list.
+ // @return the new length of the list
+ push(value:V):number;
+
+ // Adds an array of values to the end of the list.
+ pushAll(values:V[]):void;
+
+ // Creates an IndexReference at the given index. If canBeDeleted is true, then a delete over the index will delete
+ // the reference. Otherwise the reference will shift to the beginning of the deleted range.
+ registerReference(index:number, canBeDeleted:boolean):IndexReference>;
+
+ // Removes the item at the given index from the list.
+ remove(index:number):void;
+
+ // Removes the items between startIndex (inclusive) and endIndex (exclusive).
+ removeRange(startIndex:number, endIndex:number):void;
+
+ // Removes the first instance of the given value from the list.
+ // @return whether the item was removed
+ removeValue(value:V):boolean;
+
+ // Replaces items in the list with the given items, starting at the given index.
+ replaceRange(index:number, values:V[]):void;
+
+ // Sets the item at the given index
+ set(index:number, value:V):void;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.Model
+ export class Model {
+
+ // Returns the collaborative object with the given id.
+ // @return non-null Object
+ getObject: (id:string) => CollaborativeObject;
+
+ // An estimate of the number of bytes used by data stored in the model.
+ bytesUsed:number;
+
+ // True if the model can currently redo.
+ canRedo:boolean;
+
+ // True if the model can currently undo.
+ canUndo:boolean;
+
+ // Creates the native JS object for a given collaborative object type.
+ // @return non-null Object
+ createJsObject(typeName:string):any;
+
+ // Adds an event listener to the event target.
+ // The same handler can only be added once per the type. Even if you add the same handler multiple times using the
+ // same type then it will only be called once when the event is dispatched.
+ addEventListener(type:string, listener:() => void | EventListener, opt_capture?:boolean):void;
+
+ // Starts a compound operation. If a name is given, that name will be recorded in the mutation for use in revision
+ // history, undo menus, etc. When beginCompoundOperation() is called, all subsequent edits to the data model will
+ // be batched together in the undo stack and revision history until endCompoundOperation() is called.
+ // Compound operations may be nested inside other compound operations.
+ // If the root compound operation is undoable, all nested compound operations must be undoable as well.
+ // If the root compound operation is non-undoable, nested operations can be undoable, although the entire operation
+ // will obey the root's opt_isUndoable value.
+ // Note that the compound operation MUST start and end in the same synchronous execution block. If this invariant
+ // is violated, the data model will become invalid and all future changes will fail.
+ beginCompoundOperation(opt_name?:string, opt_isUndoable?:boolean):void;
+
+
+ // Creates and returns a new collaborative object. This can be used to create custom collaborative objects.
+ // For built in types, use the specific create* functions.
+ // @return non-null Object
+ create(ref:string|Function, ...var_args:any[]):any;
+
+ // Creates a collaborative list.
+ createList(opt_initialValue?:Array):CollaborativeList;
+
+ // Creates a collaborative map.
+ createMap(opt_initialValue?:Array<[string,T]>):CollaborativeMap;
+
+ // Creates a collaborative string.
+ createString(opt_initialValue?:string):CollaborativeString;
+
+ //Ends a compound operation. This method will throw an exception if no compound operation is in progress.
+ endCompoundOperation():void;
+
+ // Returns the root of the object model.
+ getRoot():CollaborativeMap;
+
+ // The mode of the document. If true, the document is read-only. If false, it is editable.
+ isReadOnly():boolean;
+
+ // Redo the last thing the active collaborator undid.
+ redo():void;
+
+ // Removes all event listeners from this object.
+ removeAllEventListeners():void;
+
+ // Removes an event listener from the event target. The handler must be the same object as the one added.
+ // If the handler has not been added then nothing is done.
+ removeEventListener(type:string, listener:() => void | EventListener, opt_capture?:boolean):void;
+
+ // The current server revision number for this model. The revision number begins at 1 (the initial empty model)
+ // and is incremented each time the model is changed on the server (either by the current session or any
+ // other collaborator). Because this revision number includes only changes that the server knows about,
+ // it is only updated while this client is connected to the Realtime API server and it does not include changes
+ // that have not yet been saved to the server.
+ serverRevision():number;
+
+ // Serializes this data model to a JSON-based format which is compatible with the Realtime API's import/export
+ // REST API. The exported JSON can also be used with gapi.drive.realtime.loadFromJson to load an in-memory
+ // version of this data model which does not require a network connection.
+ // See https://developers.google.com/drive/v2/reference/realtime/update for more information.
+ toJson(opt_appId?:string, opt_revision?:number):string;
+
+ // Undo the last thing the active collaborator did.
+ undo():void;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.BaseModelEvent
+ interface BaseModelEvent {
+ // Whether this event bubbles.
+ bubbles : boolean;
+
+ // The list of names from the hierarchy of compound operations that initiated this event.
+ compoundOperationNames : string[];
+
+ // True if this event originated in the local session.
+ isLocal : boolean;
+
+ // True if this event originated from a redo call.
+ isRedo : boolean;
+
+ // True if this event originated from an undo call.
+ isUndo : boolean;
+
+ // Prevents an event from performing its default action. In the Realtime API, this function is only present
+ // for compatibility with the DOM event interface and therefore it does nothing.
+ preventDefault() : void;
+
+ // The id of the session that initiated this event.
+ sessionId : string;
+
+ // The collaborative object that initiated this event.
+ target : CollaborativeObject;
+
+ // The type of the event.
+ type : string;
+
+ // The user id of the user that initiated this event.
+ userId : string;
+
+ // Stops an event which bubbles from propagating to the target's parent.
+ stopPropagation() : void;
+
+ /* Parameters:
+ target
+ gapi.drive.realtime.CollaborativeObject
+ The collaborative object that initiated the event.
+ Value must not be null.
+
+ sessionId
+ string
+ The id of the session that initiated the event.
+
+ userId
+ string
+ The user id of the user that initiated the event.
+
+ compoundOperationNames
+ Array of string
+ The list of names from the hierarchy of compound operations that initiated the event.
+ Value must not be null.
+ isLocal
+ boolean
+ True if the event originated in the local session.
+
+ isUndo
+ boolean
+ True if the event originated from an undo call.
+
+ isRedo
+ boolean
+ True if the event originated from a redo call.
+ */
+ new (target:CollaborativeObject, sessionId:string, userId:string, compoundOperationNames:string[],
+ isLocal:boolean, isUndo:boolean, isRedo:boolean) : BaseModelEvent;
+ }
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.ObjectChangedEvent
+ interface ObjectChangedEvent extends BaseModelEvent {
+ // parameters as in BaseModelEvent above except for addition of:
+ // events:
+ // Array of gapi.drive.realtime.BaseModelEvent
+ // The specific events that document the changes that occurred on the object.
+ // Value must not be null.
+ new (target:CollaborativeObject, sessionId:string, userId:string, compoundOperationNames:string[],
+ isLocal:boolean, isUndo:boolean, isRedo:boolean, events:BaseModelEvent[]) : ObjectChangedEvent;
+
+ // The specific events that document the changes that occurred on the object.
+ events : BaseModelEvent[];
+ }
+
+
+ // Complete
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.Document
+ export class Document {
+ // Whether the document is closed. Read-only; call close() to close the document.
+ isClosed : boolean;
+
+ // Whether the document is stored in Google Drive. Read-only.
+ // This property is false for documents created using gapi.drive.realtime.newInMemoryDocument or
+ // gapi.drive.realtime.loadFromJson and true for all other documents.
+ isInGoogleDrive : boolean;
+
+ // The approximate amount of time (in milliseconds) that changes have been waiting to be saved in Google Drive.
+ // If there are no unsaved changes or this is an in-memory document, this value is always 0.
+ // This value should remain low (for example, less than a few seconds) as long as the network is healthy and
+ // changes are being saved as quickly as they are generated. If the network is unreliable or down, or if changes
+ // are being made to the model more quickly than they can be saved, this value will continue to grow until the
+ // network catches up and the changes are successfully saved.
+ saveDelay : number;
+
+ // Adds an event listener to the event target. The same handler can only be added once per the type.
+ // Even if you add the same handler multiple times using the same type then it will only be called once when
+ // the event is dispatched.
+ addEventListener(type:string, listener:GoogEventHandler, opt_capture?:boolean) : void;
+
+ // Closes the document and disconnects from the server.
+ // After this function is called, event listeners will no longer fire and attempts to access the document, model,
+ // or model objects will throw a gapi.drive.realtime.DocumentClosedError.
+ // Calling this function after the document has been closed will have no effect.
+ close():void;
+
+ // Gets an array of collaborators active in this session. Each collaborator is a jsMap with these fields:
+ // sessionId, userId, displayName, color, isMe, isAnonymous.
+ getCollaborators() : Collaborator[];
+
+ // Gets the collaborative model associated with this document.
+ // @return non-null Model
+ getModel():Model;
+
+ // Removes all event listeners from this object.
+ removeAllEventListeners() : void;
+
+ // Removes an event listener from the event target. The handler must be the same object as the one added.
+ // If the handler has not been added then nothing is done.
+ removeEventListener(type:string, listener:GoogEventHandler, opt_capture?:boolean) : void;
+
+ // Saves a copy of this document to a new file. After this function is called, all changes to this document no
+ // longer affect the old document and are instead saved to the new file.
+ // The provided file ID must refer to a valid file in Drive which does not have any Realtime data for your app.
+ // This function can also be used on an in-memory file to convert it to a Drive-connected file.
+ saveAs(fileId:string) : void;
+
+ }
+}
+
+
+declare module gapi.drive.realtime.databinding {
+ // COMPLETE
+ // https://developers.google.com/google-apps/realtime/reference/gapi.drive.realtime.databinding.Binding
+ export interface Binding {
+ // Throws gapi.drive.realtime.databinding.AlreadyBoundError If domElement has already been bound.
+
+ // The collaborative object to bind.
+ collaborativeObject : CollaborativeObject;
+
+ // The DOM element that the collaborative object is bound to. Value must not be null.
+ domElement : Element;
+
+ // Unbinds the domElement from collaborativeObject.
+ unbind() : void;
+ }
+
+ export function bindString(s:CollaborativeString, textinput:HTMLInputElement) : Binding
+}
+
+
+declare module gapi.drive.realtime.EventType {
+ export var TEXT_INSERTED: string
+ export var TEXT_DELETED: string
+ export var OBJECT_CHANGED: string
+}
+
+
+// rtclient is a global var introduced by realtime-client-utils.js
+declare module rtclient {
+ // INCOMPLETE
+ export interface RealtimeLoader {
+ start():void;
+ load():void;
+ }
+ interface RealtimeLoaderFactory {
+ new (options:LoaderOptions) : RealtimeLoader;
+ }
+
+ // ***********************************
+ // The remainder of this file types some (not all) things in realtime-client-utils.js, found here:
+ // https://developers.google.com/google-apps/realtime/realtime-quickstart
+ // and
+ // https://apis.google.com/js/api.js
+ // ***********************************
+
+
+ // Complete
+ export interface LoaderOptions {
+ // Your Application ID from the Google APIs Console.
+ appId: string;
+
+ // Autocreate files right after auth automatically.
+ autoCreate: boolean;
+
+ // Client ID from the console.
+ clientId: string;
+
+ // The ID of the button to click to authorize. Must be a DOM element ID.
+ authButtonElementId: string;
+
+ // The MIME type of newly created Drive Files. By default the application
+ // specific MIME type will be used:
+ // application/vnd.google-apps.drive-sdk.
+ newFileMimeType: string;
+ //newFileMimeType = null // default
+
+ // Function to be called to initialize custom Collaborative Objects types.
+ registerTypes: () => void;
+
+ // The name of newly created Drive files, if no title is specified.
+ defaultTitle: string;
+
+ // Function to be called after authorization and before loading files.
+ afterAuth: () => void;
+
+ // Function to be called when a Realtime model is first created.
+ initializeModel: (model:gapi.drive.realtime.Model) => void;
+
+ // Function to be called every time a Realtime file is loaded.
+ onFileLoaded: (rtdoc:gapi.drive.realtime.Document) => void;
+ }
+
+ // INCOMPLETE
+ export interface DriveAPIFileResource {
+ id: string;
+ }
+
+ // INCOMPLETE
+ export interface ClientUtils {
+ // INCOMPLETE
+ params: {
+ // string containing one or more file ids separated by spaces.
+ fileIds : string
+ };
+ RealtimeLoader : RealtimeLoaderFactory;
+
+ /**
+ * Creates a new Realtime file.
+ * @param title {string} title of the newly created file.
+ * @param mimeType {string} the MIME type of the new file.
+ * @param callback {(file:DriveAPIFileResource) => void} the callback to call after creation.
+ */
+ createRealtimeFile(title:string, mimeType:string, callback:(file:DriveAPIFileResource) => void) : void;
+ }
+
+ export var RealtimeLoader : RealtimeLoaderFactory
+
+ /**
+ * Creates a new Realtime file.
+ * @param title {string} title of the newly created file.
+ * @param mimeType {string} the MIME type of the new file.
+ * @param callback {(file:DriveAPIFileResource) => void} the callback to call after creation.
+ */
+ export function createRealtimeFile(title:string, mimeType:string, callback:(file:DriveAPIFileResource) => void) : void
+}
+
+// INCOMPLETE
+declare module rtclient.params {
+ // string containing one or more file ids separated by spaces.
+ export var fileIds:string
+}
+