Adding securetoolurl and secureicon fields
[moodle.git] / mod / lti / mod_form.js
CommitLineData
6831c7cd
CS
1(function(){
2 var Y;
996b0fd9 3
6831c7cd
CS
4 M.mod_lti = M.mod_lti || {};
5
6 M.mod_lti.editor = {
7 init: function(yui3, settings){
8 if(yui3){
9 Y = yui3;
996b0fd9 10 }
996b0fd9 11
16e8f130 12 var self = this;
6831c7cd
CS
13 this.settings = Y.JSON.parse(settings);
14
15 this.urlCache = {};
16
17 this.addOptGroups();
18
19 var typeSelector = Y.one('#id_typeid');
20 typeSelector.on('change', function(e){
606ab1a1
CS
21 self.updateAutomaticToolMatch();
22
6831c7cd
CS
23 self.toggleEditButtons();
24 });
25
26 this.createTypeEditorButtons();
27
28 this.toggleEditButtons();
29
30 var textAreas = new Y.NodeList([
31 Y.one('#id_toolurl'),
32 Y.one('#id_resourcekey'),
33 Y.one('#id_password')
34 ]);
35
36 var debounce;
37 textAreas.on('keyup', function(e){
38 clearTimeout(debounce);
39
40 //If no more changes within 2 seconds, look up the matching tool URL
41 debounce = setTimeout(function(){
42 self.updateAutomaticToolMatch();
43 }, 2000);
44 });
45
46 self.updateAutomaticToolMatch();
47 },
48
16e8f130
CS
49 clearToolCache: function(){
50 this.urlCache = {};
51 },
52
6831c7cd 53 updateAutomaticToolMatch: function(){
16e8f130
CS
54 var self = this;
55
6831c7cd 56 var toolurl = Y.one('#id_toolurl');
606ab1a1 57 var typeSelector = Y.one('#id_typeid');
6831c7cd
CS
58 var automatchToolDisplay = Y.one('#lti_automatch_tool');
59
60 if(!automatchToolDisplay){
61 automatchToolDisplay = Y.Node.create('<span />')
62 .set('id', 'lti_automatch_tool')
63 .setStyle('padding-left', '1em');
64
65 toolurl.insert(automatchToolDisplay, 'after');
66 }
67
68 var url = toolurl.get('value');
996b0fd9 69
16e8f130
CS
70 //Hide the display if the url box is empty
71 if(!url){
6831c7cd 72 automatchToolDisplay.setStyle('display', 'none');
16e8f130
CS
73 } else {
74 automatchToolDisplay.set('innerHTML', '');
75 automatchToolDisplay.setStyle('display', '');
76 }
77
78 var selectedToolType = typeSelector.get('value');
79 var selectedOption = typeSelector.one('option[value=' + selectedToolType + ']');
80
81 //A specific tool type is selected (not "auto")"
82 if(selectedToolType > 0){
83 //If the entered domain matches the domain of the tool configuration...
84 var domainRegex = /(?:https?:\/\/)?(?:www\.)?([^\/]+)(?:\/|$)/i;
85 var match = domainRegex.exec(url);
86 if(match && match[1] && match[1].toLowerCase() === selectedOption.getAttribute('domain').toLowerCase()){
87 automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.green_check_icon_url + '" />' + M.str.lti.using_tool_configuration + selectedOption.get('text'));
88 } else {
89 //The entered URL does not match the domain of the tool configuration
90 automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.warning_icon_url + '" />' + M.str.lti.domain_mismatch);
91 }
92
6831c7cd
CS
93 return;
94 }
95
96 var key = Y.one('#id_resourcekey');
97 var secret = Y.one('#id_password');
98
99 //We don't care what tool type this tool is associated with if it's manually configured'
100 if(key.get('value') !== '' && secret.get('value') !== ''){
16e8f130 101 automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.green_check_icon_url + '" />' + M.str.lti.custom_config);
6831c7cd
CS
102 } else {
103 var continuation = function(toolInfo){
6831c7cd 104 if(toolInfo.toolname){
16e8f130 105 automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.green_check_icon_url + '" />' + M.str.lti.using_tool_configuration + toolInfo.toolname);
6831c7cd
CS
106 } else {
107 //Inform them custom configuration is in use
108 if(key.get('value') === '' || secret.get('value') === ''){
16e8f130 109 automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.warning_icon_url + '" />' + M.str.lti.tool_config_not_found);
996b0fd9
CS
110 }
111 }
6831c7cd
CS
112 };
113
114 //Cache urls which have already been checked to increaes performance
115 if(self.urlCache[url]){
116 continuation(self.urlCache[url]);
117 } else {
118 self.findToolByUrl(url, function(toolInfo){
119 self.urlCache[url] = toolInfo;
120
121 continuation(toolInfo);
122 });
123 }
124 }
125 },
126
127 getSelectedToolTypeOption: function(){
128 var typeSelector = Y.one('#id_typeid');
129
130 return typeSelector.one('option[value=' + typeSelector.get('value') + ']');
131 },
132
133 /**
134 * Separate tool listing into option groups. Server-side select control
135 * doesn't seem to support this.
136 */
137 addOptGroups: function(){
138 var typeSelector = Y.one('#id_typeid');
139
140 if(typeSelector.one('option[courseTool=1]')){
141 //One ore more course tools exist
142
143 var globalGroup = Y.Node.create('<optgroup />')
144 .set('id', 'global_tool_group')
145 .set('label', M.str.lti.global_tool_types);
146
147 var courseGroup = Y.Node.create('<optgroup />')
148 .set('id', 'course_tool_group')
149 .set('label', M.str.lti.course_tool_types);
150
606ab1a1 151 var globalOptions = typeSelector.all('option[globalTool=1]').remove().each(function(node){
6831c7cd
CS
152 globalGroup.append(node);
153 });
154
606ab1a1 155 var courseOptions = typeSelector.all('option[courseTool=1]').remove().each(function(node){
6831c7cd 156 courseGroup.append(node);
996b0fd9 157 });
6831c7cd 158
606ab1a1
CS
159 if(globalOptions.size() > 0){
160 typeSelector.append(globalGroup);
161 }
162
163 if(courseOptions.size() > 0){
164 typeSelector.append(courseGroup);
165 }
996b0fd9 166 }
6831c7cd
CS
167 },
168
169 /**
170 * Adds buttons for creating, editing, and deleting tool types.
171 * Javascript is a requirement to edit course level tools at this point.
172 */
173 createTypeEditorButtons: function(){
16e8f130
CS
174 var self = this;
175
6831c7cd
CS
176 var typeSelector = Y.one('#id_typeid');
177
178 var createIcon = function(id, tooltip, iconUrl){
179 return Y.Node.create('<a />')
180 .set('id', id)
181 .set('title', tooltip)
182 .setStyle('margin-left', '.5em')
183 .set('href', 'javascript:void(0);')
184 .append(Y.Node.create('<img src="' + iconUrl + '" />'));
185 }
186
187 var addIcon = createIcon('lti_add_tool_type', M.str.lti.addtype, this.settings.add_icon_url);
188 var editIcon = createIcon('lti_edit_tool_type', M.str.lti.edittype, this.settings.edit_icon_url);
189 var deleteIcon = createIcon('lti_delete_tool_type', M.str.lti.deletetype, this.settings.delete_icon_url);
190
191 editIcon.on('click', function(e){
192 var toolTypeId = typeSelector.get('value');
193
194 if(self.getSelectedToolTypeOption().getAttribute('editable')){
195 window.open(self.settings.instructor_tool_type_edit_url + '&action=edit&typeid=' + toolTypeId, 'edit_tool');
196 } else {
197 alert(M.str.lti.cannot_edit);
198 }
199 });
200
201 addIcon.on('click', function(e){
202 window.open(self.settings.instructor_tool_type_edit_url + '&action=add', 'add_tool');
203 });
204
205 deleteIcon.on('click', function(e){
206 var toolTypeId = typeSelector.get('value');
207
208 if(self.getSelectedToolTypeOption().getAttribute('editable')){
209 if(confirm(M.str.lti.delete_confirmation)){
16e8f130 210 self.deleteTool(toolTypeId);
6831c7cd
CS
211 }
212 } else {
213 alert(M.str.lti.cannot_delete);
214 }
215 });
216
217 typeSelector.insert(addIcon, 'after');
218 addIcon.insert(editIcon, 'after');
219 editIcon.insert(deleteIcon, 'after');
220 },
221
222 toggleEditButtons: function(){
223 var lti_edit_tool_type = Y.one('#lti_edit_tool_type');
224 var lti_delete_tool_type = Y.one('#lti_delete_tool_type');
225
226 //Make the edit / delete icons look enabled / disabled.
227 //Does not work in older browsers, but alerts will catch those cases.
228 if(this.getSelectedToolTypeOption().getAttribute('editable')){
229 lti_edit_tool_type.setStyle('opacity', '1');
230 lti_delete_tool_type.setStyle('opacity', '1');
231 } else {
232 lti_edit_tool_type.setStyle('opacity', '.2');
233 lti_delete_tool_type.setStyle('opacity', '.2');
234 }
235 },
236
16e8f130 237 addToolType: function(toolType){
6831c7cd
CS
238 var typeSelector = Y.one('#id_typeid');
239 var course_tool_group = Y.one('#course_tool_group');
240
241 var option = Y.Node.create('<option />')
16e8f130
CS
242 .set('text', toolType.name)
243 .set('value', toolType.id)
6831c7cd
CS
244 .set('selected', 'selected')
245 .setAttribute('editable', '1')
16e8f130
CS
246 .setAttribute('courseTool', '1')
247 .setAttribute('domain', toolType.tooldomain);
6831c7cd
CS
248
249 if(course_tool_group){
250 course_tool_group.append(option);
251 } else {
252 typeSelector.append(option);
253 }
16e8f130
CS
254
255 //Adding the new tool may affect which tool gets matched automatically
256 this.clearToolCache();
257 this.updateAutomaticToolMatch();
6831c7cd
CS
258 },
259
16e8f130 260 updateToolType: function(toolType){
6831c7cd
CS
261 var typeSelector = Y.one('#id_typeid');
262
16e8f130
CS
263 var option = typeSelector.one('option[value=' + toolType.id + ']');
264 option.set('text', toolType.name)
265 .set('domain', toolType.tooldomain);
266
267 //Editing the tool may affect which tool gets matched automatically
268 this.clearToolCache();
269 this.updateAutomaticToolMatch();
270 },
271
272 deleteTool: function(toolTypeId){
273 var self = this;
274
275 Y.io(self.settings.instructor_tool_type_edit_url + '&action=delete&typeid=' + toolTypeId, {
276 on: {
277 success: function(){
278 self.getSelectedToolTypeOption().remove();
279
280 //Editing the tool may affect which tool gets matched automatically
281 self.clearToolCache();
282 self.updateAutomaticToolMatch();
283 },
284 failure: function(){
285
286 }
287 }
288 });
6831c7cd
CS
289 },
290
291 findToolByUrl: function(url, callback){
16e8f130
CS
292 var self = this;
293
6831c7cd 294 Y.io(self.settings.ajax_url, {
16e8f130 295 data: {action: 'find_tool_config',
6831c7cd
CS
296 course: self.settings.courseId,
297 toolurl: url
298 },
996b0fd9 299
6831c7cd
CS
300 on: {
301 success: function(transactionid, xhr){
302 var response = xhr.response;
303
304 var toolInfo = Y.JSON.parse(response);
305
306 callback(toolInfo);
307 },
308 failure: function(){
996b0fd9 309
6831c7cd
CS
310 }
311 }
312 });
313 }
996b0fd9 314
6831c7cd
CS
315 };
316})();