A couple bugfixes related to instructor defined tools
[moodle.git] / mod / lti / mod_form.js
CommitLineData
6831c7cd
CS
1(function(){
2 var Y;
3 var self;
996b0fd9 4
6831c7cd
CS
5 M.mod_lti = M.mod_lti || {};
6
7 M.mod_lti.editor = {
8 init: function(yui3, settings){
9 if(yui3){
10 Y = yui3;
996b0fd9 11 }
996b0fd9 12
6831c7cd
CS
13 self = this;
14 this.settings = Y.JSON.parse(settings);
15
16 this.urlCache = {};
17
18 this.addOptGroups();
19
20 var typeSelector = Y.one('#id_typeid');
21 typeSelector.on('change', function(e){
606ab1a1
CS
22 self.updateAutomaticToolMatch();
23
6831c7cd
CS
24 self.toggleEditButtons();
25 });
26
27 this.createTypeEditorButtons();
28
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);
40
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 },
49
50 updateAutomaticToolMatch: function(){
51 var toolurl = Y.one('#id_toolurl');
606ab1a1 52 var typeSelector = Y.one('#id_typeid');
6831c7cd
CS
53 var automatchToolDisplay = Y.one('#lti_automatch_tool');
54
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 }
62
63 var url = toolurl.get('value');
996b0fd9 64
606ab1a1 65 if(!url || typeSelector.get('value') > 0){
6831c7cd
CS
66 automatchToolDisplay.setStyle('display', 'none');
67 return;
68 }
69
70 var key = Y.one('#id_resourcekey');
71 var secret = Y.one('#id_password');
72
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', '');
79
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.');
996b0fd9
CS
86 }
87 }
6831c7cd
CS
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;
96
97 continuation(toolInfo);
98 });
99 }
100 }
101 },
102
103 getSelectedToolTypeOption: function(){
104 var typeSelector = Y.one('#id_typeid');
105
106 return typeSelector.one('option[value=' + typeSelector.get('value') + ']');
107 },
108
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');
115
116 if(typeSelector.one('option[courseTool=1]')){
117 //One ore more course tools exist
118
119 var globalGroup = Y.Node.create('<optgroup />')
120 .set('id', 'global_tool_group')
121 .set('label', M.str.lti.global_tool_types);
122
123 var courseGroup = Y.Node.create('<optgroup />')
124 .set('id', 'course_tool_group')
125 .set('label', M.str.lti.course_tool_types);
126
606ab1a1 127 var globalOptions = typeSelector.all('option[globalTool=1]').remove().each(function(node){
6831c7cd
CS
128 globalGroup.append(node);
129 });
130
606ab1a1 131 var courseOptions = typeSelector.all('option[courseTool=1]').remove().each(function(node){
6831c7cd 132 courseGroup.append(node);
996b0fd9 133 });
6831c7cd 134
606ab1a1
CS
135 if(globalOptions.size() > 0){
136 typeSelector.append(globalGroup);
137 }
138
139 if(courseOptions.size() > 0){
140 typeSelector.append(courseGroup);
141 }
996b0fd9 142 }
6831c7cd
CS
143 },
144
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');
151
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 }
160
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);
164
165 editIcon.on('click', function(e){
166 var toolTypeId = typeSelector.get('value');
167
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 });
174
175 addIcon.on('click', function(e){
176 window.open(self.settings.instructor_tool_type_edit_url + '&action=add', 'add_tool');
177 });
178
179 deleteIcon.on('click', function(e){
180 var toolTypeId = typeSelector.get('value');
181
182 if(self.getSelectedToolTypeOption().getAttribute('editable')){
183 if(confirm(M.str.lti.delete_confirmation)){
184
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(){
996b0fd9 191
6831c7cd
CS
192 }
193 }
194 });
195 }
196 } else {
197 alert(M.str.lti.cannot_delete);
198 }
199 });
200
201 typeSelector.insert(addIcon, 'after');
202 addIcon.insert(editIcon, 'after');
203 editIcon.insert(deleteIcon, 'after');
204 },
205
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');
209
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 },
220
221 addToolType: function(text, value){
222 var typeSelector = Y.one('#id_typeid');
223 var course_tool_group = Y.one('#course_tool_group');
224
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');
231
232 if(course_tool_group){
233 course_tool_group.append(option);
234 } else {
235 typeSelector.append(option);
236 }
237 },
238
239 updateToolType: function(text, value){
240 var typeSelector = Y.one('#id_typeid');
241
242 var option = typeSelector.one('option[value=' + value + ']');
243 option.set('text', text);
244 },
245
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 },
996b0fd9 252
6831c7cd
CS
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(){
996b0fd9 262
6831c7cd
CS
263 }
264 }
265 });
266 }
996b0fd9 267
6831c7cd
CS
268 };
269})();