In Watching for server side changes from the client html service, I showed how to watch for server side positional or data changes from the client and be woken up when they happen. That post covered spreadsheets, but you can also do the same thing with Documents. The client side is almost exactly the same, but of course the server side has changed. Watching documents is a little more complex, because the data in them is less structured, the object model is a little more complicated and there's more things to watch out for. However the client side is as simple as before. Here's an example of how you would use it.
var dataWatch = ClientWatcher.addWatcher ({ domain: { app:"Docs", scope:"Doc" } });
dataWatch.watch (function (current,pack,watcher) { // do something - the latest data is in current.data , and the latest active selection information is in current.active. }); It really is that simple, and this will allow your add-on to react to changes that are happening server side right away. Of course there's a lot going on behind the scenes that I'll cover later, but first let's look at what gets passed to you. Callback argumentsYour callback passed to the .watch() method would typically react to server side changes - perhaps visualizing the updated data or using the active range is some way. You receive these arguments each time a change happens in the sheet. currentThis is the current status of the data in the sheet server side. Its contents depends on what you've asked to be watched - we'll look at how to do that later. Assuming you've asked to monitor data and selection changes, it will look like this.
PackThis is not normally required, but the pack object contains info on what has actually changed. For example, if you are monitoring both data changes and active changes you can test pack.changed.active and packed.changed.data to see which (maybe both) has changed to provoke your function being called. watcherThis is the watcher object and is passed for convenience. You can use it to get more information on the polling process. For example, watcher.getStatus() will provide information on how many polling requests there have been, hot many resulted in changes, and even how much time its spent waiting - a good measure for checking the latency of client/server requests. Just divide the wait time by status.serial and you'll get the average latency. Some useful methods available via the watcher object
DemoYou can try some of the capabilities using the demo Setting up a watcher.The default values are set up for sheets. So it needs a couple of changes to watch for Docs // default settings for a Watcher request var watch = Utils.vanMerge ([{ pollFrequency:2500, // if this is 0, then polling is not done, and it needs self.poke() id: '' , // Watcher id pollVisibleOnly:true, // just poll if the page is actually visible watch: { active: true, // whether to watch for changes to active (this is the selection. in docs it also triggers if cursor changes) data: true, // whether to watch for data content changes sheets:true // watch for changes in number/names of sheets (only for app.sheets) }, checksum:{ active:"", // the active checksum last time polled data:"", // the data checksum last time polled sheets:"" // the sheets in the workbook last time polled }, domain: { app: "Sheets", // for sheets or docs scope: "Sheet", // Sheet, Active or Range - sheet will watch the datarange range: "", // if range, specifiy a range to watch sheet: "", // a sheet name - if not given, the active sheet will be used property:"Values", // Values,Backgrounds etc... fiddler:true, // whether to create a fiddler to mnipulate data (ignored for nondata property) applyFilters:false // whether to apply filters } },options || {}]); You can override these changes by passing an options object when you add the watcher. For example, here is one that watches for changes in data, but does not monitor for changes in active selection.
var watch = ClientWatcher.addWatcher ({ watch:{active:false}, domain:{app:'Docs',scope:'Doc'} }); Note that right now the only property that is watched in documents is the text content, unlike the Spreadsheet watcher which can watch for color changes and all sorts of stuff. I made add this to the document watcher too if enough people ask for it.Stopping pollingYou can use watcher.stop() to finish polling (it will stop on completion of the currently active poll) and watcher.restart().watch(callback) to start it up again. Removing a watcher ClientWatcher.remove (watcher), will stop it, then remove it. Watching parts of Docs - scopeBy default the entire active document is watched for changes. But you can watch just the active selection or cursor position, a named range or a path (more on that later). Note that the selection and cursor position are different things in Docs (unlike in Sheets where they are the same) - so sometimes the selection will be null, or the cursor will be null to indicate what the user is up to. To avoid getting two callbacks for each cursor/selection changes this watch is combined and provoked by either. Watch for data changes in the entire document var valuesWatch = ClientWatcher.addWatcher ({ domain:{scope:"Doc",app:"Docs"} });
Watch for data changes in the active selection or cursor position var valuesWatch = ClientWatcher.addWatcher ({ domain:{scope:"Active",app:"Docs"} });
|
Script | runs on | purpose |
Include | Server | Pulls in server side code to run on the client |
Provoke | Client | Manages conversation with server side |
Utils | Client/Server | Various Utilities |
DomUtils | Client | Dom manipulation stuff - just required for demo |
Fiddler | Client/Server | Manage data for structure access. I'm running this on client, but could be server also if manipulation required before sending |
ClientWatcher | Client | The watcher namespace |
ServerWatcher | Server | The co-operating server namespace |
main.js.html | Client | Just for demo - sheets |
addon | Server | Will detect whether its doing sheets or docs and load the appropiate client files |
index.html | Client | Just for demo - sheets |
mainDocs.js.html | Client | Just for demo - docs |
indexDocs.html | Client | Just for demo - docs |
Promises
<script src="//cdnjs.cloudflare.com/ajax/libs/es6-promise/3.2.1/es6-promise.min.js"></script>
Visibility
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ifvisible/1.0.6/ifvisible.min.js"></script>
pollVisibilityOnly:false
Demo
You want to learn Google Apps Script?
Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly.
If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.
Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly.
If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.