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