-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstudentmatrix-api.js
295 lines (275 loc) · 12.4 KB
/
studentmatrix-api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/**
* @file
* Contains examples of how to write plugins for StudentMatrix, and some other
* API docs.
*/
/**
* Plugins are declared by adding an entry to StudentMatrix.plugins. This entry
* contains declarations of whatever components are included in the plugin. Each
* type of component are declared in its own way. Examples follow.
*/
StudentMatrix.plugins.example = {
// Each plugin must provide a meta-description of itself, including version
// number and an URL where code updates can be found. Version number should
// increase in decimals when the API is not broken, and by integers when any
// exposed API becomes broken. Dependencies are declared against the mininmum
// API version -- dependency on core 1.1 also works with core 1.2 (but not
// 2.0, as APIs may have changed between integer versions). Note that version
// and dependencies are declared as strings, to allow incrementing 1.9 to
// 1.10 (which is different from 1.1).
name : 'Example plugin',
description : 'One or two sentences describing what the plugin does.',
version : '1.0',
updateUrl : 'https://raw.github.com/Itangalo/studentmatrix/3.x/studentmatrix-api.js',
// The cell reference below refers to the spreadsheet on
// https://docs.google.com/spreadsheet/ccc?key=0AjgECFpHWbvRdE4yVHZRcGxEamVWUE1TalBLby12blE
// and may be used to broadcast information about new versions. Optional.
cell : 'A1',
dependencies : {
core : '3.0',
modules : {
menu : '1.0',
},
plugins : {
myPlugin : '1.1',
},
},
// Any handlers that should be possible to call using StudentMatrix.addPluginHandler('pluginName', 'callbackFunction').
// These handlers are normally used to process responses in forms, and they
// should all take an argument containing the event information for the UiApp.
// Normally they will also return the UiApp, to allow further processing (such
// as closing it).
handlers : {
myHandler : function(eventInfo) {
var app = UiApp.getActiveApplication();
// Do some stuff.
return app;
},
},
// 'settings' components are used to store globally available information.
// Since a plugin can have multiple settings, they are declared as sub
// properties.
settings : {
mySetting : {
// The settings will be displayed with other settings in the same group.
group : 'Examples',
},
// All options used by the setting are declared in the options property,
// along with default values. If the name of the options match any
// properties used through StudentMatrix.getProperty(), the default values
// will be used as fallback by that function.
options : {
color : 'hotpink',
},
// The options builder takes care of building a form where the user changes
// the settings. All elements should be added to the container. Any elements
// that should be processed should be added to the handler. Any default
// values are passed in the defaults parameter, to set start values of UI
// elements. Default values are built using StudentMatrix.getProperty(), and
// if nothing is found the defaults in the options property is used.
optionsBuilder : function(handler, container, defaults) {
var app = UiApp.getActiveApplication();
var textBox = app.createTextBox().setName('color').setText(defaults.color);
container.add(textBox);
handler.addCallbackElement(textBox);
},
// Normally, the options are read off the eventInfo when saving the settings
// form, and stored using StudentMatrix.setProperty(). However, if more
// complex processing is required you can declare an optionsSaver function.
// This function must then take care of storing *all* the options for this
// component.
optionsSaver : function(eventInfo) {
var processedValue;
// Do complex stuff.
StudentMatrix.setProperty(processedValue, 'settingID');
},
},
// 'studentActions' components are actions that can be run on all or selected
// students. Since a plugin can have multiple studentActions, they are
// declared as sub properties.
studentActions : {
myStudentAction : {
name : 'Visible name of the action',
group : 'Examples',
description : 'A longer description, explaining to the user what this action does in a sentence or two.',
helpLink : 'http://link.to/help-page-with-further-information',
// The processor is the method doing the actual work on each student entry.
// If your action uses options, they are passed in the options parameter.
// If you for some reason want to know which row is being processed, that
// is passed in the row parameter.
processor : function(row, options) {
// You will most likely want to use some fetchers, to get various data
// derived from the student row.
var studentNameCell = StudentMatrix.components.fetchers.studentName(row);
studentNameCell.setFontWeight('bold');
studentNameCell.setBackgroundColor(options.color);
},
// Validators can be used to disallow the action in some circumstances. If
// no validator is declared, you can always run the action.
validator : function() {
// Run checks here. A null return means ok. A return of anything else
// will be used as error message and displayed to the user.
if ('ok' == true) {
return;
}
else {
return 'This action cannot be run on Thursdays.';
}
},
// Options builders are used to display options to the user before running
// the action. The builder is passed a handler and a container. All
// elements that should be displayed should be added to the container (to
// allow scrolling), and any elements that should be evaluated must be
// added to the handler.
optionsBuilder : function(handler, container) {
var app = UiApp.getActiveApplication();
container.add(app.createHTML('Background color'));
var color = app.createTextBox().setId('color').setName('color');
container.add(color);
handler.addCallbackElement(color);
},
// Any entries in the options property will be used to look for values
// added by the options builder. It will also be used for setting default
// values, in case they aren't populated by the builder. This is also a
// neat trick to build expensive objects only once.
options : {
color : 'blue',
someOtherOption : 'some other default value',
expensiveObject : SpreadsheetApp.getActiveRange(),
},
// In case the plugin options cannot just be read from eventInfo, you need
// an optionsProcessor. If you declare this function, it needs to take
// responsibility for building *all* your options -- not just the
// difficult ones.
optionsProcessor : function(eventInfo) {
var options = {};
options.color = ensureColorCode(eventInfo.color);
options.someOtherOption = eventInfo.someOtherOption;
// Note that any default values are overwritten.
options.expensiveObject = SpreadsheetApp.getActiveRange();
return options;
},
},
},
// Fetchers are usually called from within studentActions, to fetch data
// related to a particular student row. Fetchers usually only take the row
// number as argument, and use that to build whatever item is relevant.
// Returning false signals that the fetch process could not be completed.
// Since a plugin can have multiple fetchers, they are declared as sub
// properties.
fetchers : {
// This example fetcher returns the cell containing the student's name.
// There is actually a fetcher 'studentColumnCell' and 'studentColumnValue'
// that could do this fetching (and you really should reuse existing
// fetchers rather than building your own), but this still serves as an
// example.
myfetcher : function(row) {
return StudentMatrix.mainSheet().getRange(row, StudentMatrix.getProperty('StudentMatrixColumns', 'studentName'));
},
},
// 'globalActions' components are similar to studentActions, but are only run
// once (and not on any student). Since a plugin can have multiple
// globalActions, they are declared as sub properties.
globalActions : {
myGlobalAction : {
name : 'Visible name of the action',
group : 'Examples',
description : 'A longer description, explaining to the user what this action does in a sentence or two.',
helpLink : 'http://link.to/help-page-with-further-information',
// The processor is the method doing the actual work.
// If your action uses options, they are passed in the options parameter.
processor : function(options) {
// Copy a file, send an e-mail, insert a new tab into the spreadsheet,
// or just display a message. Whatever you want to do with the action.
Browser.msgBox(options.message);
},
// See the example studentAction.
validator : function() {
},
// See the example studentAction.
optionsBuilder : function(handler, container) {
},
options : {
},
optionsProcessor : function(eventInfo) {
},
},
},
// Information pages can be used for building guides/wizards, or just to
// display static information (such as help pages).
infoPages : {
pageID : {
title : 'Title of the info page',
content : function(container) {
var app = UiApp.getActiveApplication();
container.add(app.createHTML('Content must be placed in the container, so it is scrollable.'));
},
doneText : 'It is possible to override text on the "done" button',
next : 'nextPageID', // Optional, used for browsing.
previous : 'previousPageID', // Optional, used for browsing.
afterProcess : function() {
// Add any code you want to run when the user clicks 'done' or 'next'
// from this information page. Optional.
},
},
},
};
/**
* Modules add new types of functionality to StudentMatrix (which are usually
* implemented by plugins), and usually contain a lot of methods and logic. New
* modules are declared by adding an entry to StudentMatrix.modules. Some module
* properties are read by StudentMatrix and have special meaning -- see example
* below.
*
* If you want to call a method inside a module as a UI handler, you can do this
* by using StudentMatrix.addModuleHandler('moduleName', 'callbackFunction').
*/
StudentMatrix.modules.example = {
// See example of plugin for explanation of this meta-description.
name : 'Example module',
description : 'One or two sentences describing what the module does.',
version : '1.0',
// Setting 'required' property to true makes it impossible to disable the module (or
// plugin) manually.
required : true,
updateUrl : 'https://raw.github.com/Itangalo/studentmatrix/3.x/studentmatrix-api.js',
cell : 'A1',
dependencies : {
core : '3.0',
modules : {
menu : '1.0',
},
plugins : {
myPlugin : '1.1',
},
},
// 'columns' property adds columns that is used by your module. You get the
// assigned column number through StudentMatrix.getProperty('StudentMatrixColumns', columnID).
// Note that the user must run the action to set up columns manually.
// Columns can be added by both modules and plugins.
columns : {
myColumnID : 'Visible lable for the column',
myColumnID2 : 'Another label',
},
// 'menuEntries' property adds menu entries to the StudentMatrix menu. Note
// that all callback functions must be global, due to how the Google script
// works. The menu entry below will need a global function called
// StudentMatrixMenu_callbackSuffix(). You can also store menu entries as
// properties, by calling
// StudentMatrix.setProperty(entry, 'StudentMatrixMenu', itemID), where the
// itemID corresponds to the callback suffix and the entry is the menu item
// object.
// Menu entries can be declared by both modules and plugins.
menuEntries : {
callbackSuffix : {
name : 'Name displayed in the menu',
weight : -4, // Lower weights floats to the top in the menu.
callback : 'path.to.internal.method', // Used for dynamic callbacks only.
arguments : ['arg1', 'arg2'], // Used for dynamic callbacks only.
disabled : true, // May be used to disable entries stored as properties.
},
},
};
// Remove the declarations above, so they aren't implemented.
delete StudentMatrix.plugins.example;
delete StudentMatrix.modules.example;