A couple bugfixes related to instructor defined tools
[moodle.git] / mod / lti / mod_form.js
1 (function(){
2     var Y;
3     var self;
4     
5     M.mod_lti = M.mod_lti || {};
7     M.mod_lti.editor = {
8         init: function(yui3, settings){
9             if(yui3){
10                 Y = yui3;
11             }
12             
13             self = this;
14             this.settings = Y.JSON.parse(settings);
16             this.urlCache = {};
18             this.addOptGroups();
20             var typeSelector = Y.one('#id_typeid');
21             typeSelector.on('change', function(e){
22                 self.updateAutomaticToolMatch();
23                 
24                 self.toggleEditButtons();
25             });
27             this.createTypeEditorButtons();
29             this.toggleEditButtons();
30             
31             var textAreas = new Y.NodeList([
32                 Y.one('#id_toolurl'),
33                 Y.one('#id_resourcekey'),
34                 Y.one('#id_password')
35             ]);
36             
37             var debounce;
38             textAreas.on('keyup', function(e){
39                 clearTimeout(debounce);
41                 //If no more changes within 2 seconds, look up the matching tool URL
42                 debounce = setTimeout(function(){
43                     self.updateAutomaticToolMatch();
44                 }, 2000);
45             });
46             
47             self.updateAutomaticToolMatch();
48         },
50         updateAutomaticToolMatch: function(){
51             var toolurl = Y.one('#id_toolurl');
52             var typeSelector = Y.one('#id_typeid');
53             var automatchToolDisplay = Y.one('#lti_automatch_tool');
55             if(!automatchToolDisplay){
56                 automatchToolDisplay = Y.Node.create('<span />')
57                                         .set('id', 'lti_automatch_tool')
58                                         .setStyle('padding-left', '1em');
59                                         
60                 toolurl.insert(automatchToolDisplay, 'after');
61             }
63             var url = toolurl.get('value');
65             if(!url || typeSelector.get('value') > 0){
66                 automatchToolDisplay.setStyle('display', 'none');
67                 return;
68             }
70             var key = Y.one('#id_resourcekey');
71             var secret = Y.one('#id_password');
73             //We don't care what tool type this tool is associated with if it's manually configured'
74             if(key.get('value') !== '' && secret.get('value') !== ''){
75                 automatchToolDisplay.set('innerHTML',  '<img style="vertical-align:text-bottom" src="' + self.settings.green_check_icon_url + '" />Using custom tool configuration.');
76             } else {
77                 var continuation = function(toolInfo){
78                     automatchToolDisplay.setStyle('display', '');
80                     if(toolInfo.toolname){
81                         automatchToolDisplay.set('innerHTML',  '<img style="vertical-align:text-bottom" src="' + self.settings.green_check_icon_url + '" />Using tool configuration: ' + toolInfo.toolname);
82                     } else {
83                         //Inform them custom configuration is in use
84                         if(key.get('value') === '' || secret.get('value') === ''){
85                             automatchToolDisplay.set('innerHTML', '<img style="vertical-align:text-bottom" src="' + self.settings.yellow_check_icon_url + '" />Tool configuration not found for this URL.');
86                         }
87                     }
88                 };
89                 
90                 //Cache urls which have already been checked to increaes performance
91                 if(self.urlCache[url]){
92                     continuation(self.urlCache[url]);
93                 } else {
94                     self.findToolByUrl(url, function(toolInfo){
95                         self.urlCache[url] = toolInfo;
97                         continuation(toolInfo);
98                     });
99                 }
100             }
101         },
103         getSelectedToolTypeOption: function(){
104             var typeSelector = Y.one('#id_typeid');
106             return typeSelector.one('option[value=' + typeSelector.get('value') + ']');
107         },
109         /**
110          * Separate tool listing into option groups. Server-side select control
111          * doesn't seem to support this.
112          */
113         addOptGroups: function(){
114             var typeSelector = Y.one('#id_typeid');
116             if(typeSelector.one('option[courseTool=1]')){
117                 //One ore more course tools exist
119                 var globalGroup = Y.Node.create('<optgroup />')
120                                     .set('id', 'global_tool_group')
121                                     .set('label', M.str.lti.global_tool_types);
123                 var courseGroup = Y.Node.create('<optgroup />')
124                                     .set('id', 'course_tool_group')
125                                     .set('label', M.str.lti.course_tool_types);
127                 var globalOptions = typeSelector.all('option[globalTool=1]').remove().each(function(node){
128                     globalGroup.append(node);
129                 });
131                 var courseOptions = typeSelector.all('option[courseTool=1]').remove().each(function(node){
132                     courseGroup.append(node);
133                 });
135                 if(globalOptions.size() > 0){
136                     typeSelector.append(globalGroup);
137                 }
138                 
139                 if(courseOptions.size() > 0){
140                     typeSelector.append(courseGroup);
141                 }
142             }
143         },
145         /**
146          * Adds buttons for creating, editing, and deleting tool types.
147          * Javascript is a requirement to edit course level tools at this point.
148          */
149         createTypeEditorButtons: function(){
150             var typeSelector = Y.one('#id_typeid');
152             var createIcon = function(id, tooltip, iconUrl){
153                 return Y.Node.create('<a />') 
154                         .set('id', id)
155                         .set('title', tooltip)
156                         .setStyle('margin-left', '.5em')
157                         .set('href', 'javascript:void(0);')
158                         .append(Y.Node.create('<img src="' + iconUrl + '" />'));
159             }
161             var addIcon = createIcon('lti_add_tool_type', M.str.lti.addtype, this.settings.add_icon_url);
162             var editIcon = createIcon('lti_edit_tool_type', M.str.lti.edittype, this.settings.edit_icon_url);
163             var deleteIcon  = createIcon('lti_delete_tool_type', M.str.lti.deletetype, this.settings.delete_icon_url);
165             editIcon.on('click', function(e){
166                 var toolTypeId = typeSelector.get('value');
168                 if(self.getSelectedToolTypeOption().getAttribute('editable')){
169                     window.open(self.settings.instructor_tool_type_edit_url + '&action=edit&typeid=' + toolTypeId, 'edit_tool');
170                 } else {
171                     alert(M.str.lti.cannot_edit);
172                 }
173             });
175             addIcon.on('click', function(e){
176                 window.open(self.settings.instructor_tool_type_edit_url + '&action=add', 'add_tool');
177             });
179             deleteIcon.on('click', function(e){
180                 var toolTypeId = typeSelector.get('value');
182                 if(self.getSelectedToolTypeOption().getAttribute('editable')){
183                     if(confirm(M.str.lti.delete_confirmation)){
185                         Y.io(self.settings.instructor_tool_type_edit_url + '&action=delete&typeid=' + toolTypeId, {
186                             on: {
187                                 success: function(){
188                                     self.getSelectedToolTypeOption().remove();
189                                 },
190                                 failure: function(){
192                                 }
193                             }
194                         });
195                     }
196                 } else {
197                     alert(M.str.lti.cannot_delete);
198                 }
199             });
201             typeSelector.insert(addIcon, 'after');
202             addIcon.insert(editIcon, 'after');
203             editIcon.insert(deleteIcon, 'after');
204         },
206         toggleEditButtons: function(){
207             var lti_edit_tool_type = Y.one('#lti_edit_tool_type');
208             var lti_delete_tool_type = Y.one('#lti_delete_tool_type');
210             //Make the edit / delete icons look enabled / disabled.
211             //Does not work in older browsers, but alerts will catch those cases.
212             if(this.getSelectedToolTypeOption().getAttribute('editable')){
213                 lti_edit_tool_type.setStyle('opacity', '1');
214                 lti_delete_tool_type.setStyle('opacity', '1');
215             } else {
216                 lti_edit_tool_type.setStyle('opacity', '.2');
217                 lti_delete_tool_type.setStyle('opacity', '.2');
218             }
219         },
221         addToolType: function(text, value){
222             var typeSelector = Y.one('#id_typeid');
223             var course_tool_group = Y.one('#course_tool_group');
225             var option = Y.Node.create('<option />')
226                             .set('text', text)
227                             .set('value', value)
228                             .set('selected', 'selected')
229                             .setAttribute('editable', '1')
230                             .setAttribute('courseTool', '1');
232             if(course_tool_group){
233                 course_tool_group.append(option);
234             } else {
235                 typeSelector.append(option);
236             }
237         },
239         updateToolType: function(text, value){
240             var typeSelector = Y.one('#id_typeid');
242             var option = typeSelector.one('option[value=' + value + ']');
243             option.set('text', text);
244         },
246         findToolByUrl: function(url, callback){
247             Y.io(self.settings.ajax_url, { 
248                 data: { action: 'find_tool_config',
249                         course: self.settings.courseId,
250                         toolurl: url
251                 },
253                 on: {
254                     success: function(transactionid, xhr){
255                         var response = xhr.response;
256                         
257                         var toolInfo = Y.JSON.parse(response);
258                         
259                         callback(toolInfo);
260                     },
261                     failure: function(){
263                     }
264                 }
265             });
266         }
268     };
269 })();