· 8 years ago · Feb 14, 2018, 01:56 AM
1/* -----------------------------------------
2Canvas Extensions Toolbar
3------------------------------------------
4
5Javascript for Chome bookmark:
6javascript:(function(){ var script=document.createElement('script'); script.src='https://ilearn.swin.edu.au/bbcswebdav/orgs/TLIP_scripts/shortcut-scripts/canvasExtentionToolbar.js'; document.head.appendChild(script); }())
7
8*/
9// get Current course ID
10
11var query_string = window.location.href;
12var query_string_split = query_string.split("/");
13window.currentCourse = query_string_split.indexOf('courses') >= 0 ? query_string_split[query_string_split.indexOf('courses') + 1] : "";
14
15window.canvasExtension = {};
16window.canvasExtension.extensionMenu = {};
17
18window.canvasExtension.dialog;
19window.canvasExtension.dialogId = "#extensionsDialog";
20
21window.canvasExtension.allItems = [];
22window.canvasExtension.allItemsAjax = [];
23window.canvasExtension.gradeBookColumns = [];
24
25
26/**
27 * init, create the extension menu, each button runs a function or opens a dialog
28 *
29 */
30window.canvasExtension.initCanvasExtensionMenu = function() {
31 window.canvasExtension.buildDialog();
32 //remove any existing extensions menu
33 $('#extensionMenu').remove();
34 //extension menu html
35 var menuHTML = " \
36 <div id='extensionMenu' class='' style='z-index: 12; background: #EEE; position: fixed; top: 0; right: 0; padding: 5px; text-align: right; box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.75); font-size: 0.5em; line-height: 1em; '> \
37 <a title='Scroll to top' onClick='window.scrollTo(0,0)' class='btn btn-default' style='padding: 0.5em; border-color: black;'><i class='icon-arrow-open-up'> </i></a> \
38 <a title='Expand all' onClick='window.canvasExtension.expandAll()' class='btn btn-info' style='padding: 0.5em; border-color: black;'><i class='icon-page-down'> </i></a> \
39 <a title='Contract all' onClick='window.canvasExtension.contractAll()' class='btn btn-info' style='padding: 0.5em; border-color: black;'><i class='icon-page-up'> </i></a> \
40 <a title='Publish all' onClick='window.canvasExtension.publishAll()' class='btn btn-success' style='padding: 0.5em; border-color: black;'><i class='icon-publish'> </i></a> \
41 <a title='Unpublish all' onClick='window.canvasExtension.unpublishAll()' class='btn' style='padding: 0.5em; border-color: black;'><i class='icon-unpublish'> </i></a> \
42 <a title='Add groups' onClick='window.canvasExtension.setupAddGroups()' class='btn btn-warning' style='padding: 0.5em; background-color: red; border-color: black;'><i class='icon-group'> </i></a> \
43 <a title='Manage GradeBook columns' onClick='window.canvasExtension.setupGradeBookColumns()' class='btn btn-warning' style='padding: 0.5em; background-color: orange; border-color: black;'><i class='icon-gradebook'> </i></a> \
44 <a title='Remove assignment dates' onClick='window.canvasExtension.runDialog(\"RemoveAssignmentDates\")' class='btn btn-danger' style='padding: 0.5em; color: black; background-color: yellow; border-color: black;'><i class='icon-calendar-clock'> </i></a> \
45 <a title='Find/remove empty items' onClick='window.canvasExtension.setupEmptyItems()' class='btn btn-danger' style='padding: 0.5em; background-color: green; border-color: black;'><i class='icon-document'> </i></a> \
46 <a title='Remove empty modules and assignment groups' onClick='window.canvasExtension.runDialog(\"RemoveEmptyModules\")' class='btn btn-danger' style='padding: 0.5em; background-color: blue; border-color: black;'><i class='icon-module'> </i></a> \
47 <a title='Expand all Quizzes' onClick='window.canvasExtension.expandQuiz()' class='btn btn-info' style='padding: 0.5em; color: white; background-color: purple;'><i class='icon-quiz'></i></a> \
48 <a title='Reformat all Quizzes' onClick='window.canvasExtension.reformatQuiz()' class='btn btn-info' style='padding: 0.5em; color: white; background-color: violet;'><i class='icon-question'></i></a> \
49 </div> \
50 ";
51 //add extension menu to page
52 window.extensionMenu = $('body').append(menuHTML);
53}
54
55
56
57/**
58 * setup the dialog window, add it to the page
59 *
60 */
61window.canvasExtension.buildDialog = function() {
62 //destroy any existing dialogs
63 //if element exists, remove
64 if ($(window.canvasExtension.dialog) > 0) window.canvasExtension.dialog.dialog("destroy");
65 $(window.canvasExtension.dialogId).remove();
66 //add dialog
67 $('body').append('<div id="' + window.canvasExtension.dialogId.substring(1) + '" title=""></div>');
68 window.canvasExtension.dialog = $(window.canvasExtension.dialogId);
69 var dialogHtml = "";
70 window.canvasExtension.dialog.append(dialogHtml);
71}
72
73// Reformat all quiz questions/answer
74window.canvasExtension.expandQuiz = function() {
75 console.log("TESTING ORIGINAL QUIZ FUNCTION")
76 $('.icon-edit.standalone-icon:visible, .element_toggler[aria.expanded="false"]:visible').click();
77 $('.icon-edit.standalone-icon:visible, .element_toggler[aria.expanded="false"]:visible').click();
78 // could be this or icon-edit standalone-icon
79}
80window.canvasExtension.reformatQuiz = function() {
81 var currentEditor = tinyMCE.activeEditor
82 // get our current focused editor
83 tinymce.activeEditor.execCommand('selectAll');
84 tinymce.activeEditor.execCommand('RemoveFormat');
85 // select all and remove formatting
86 var tinyContent = currentEditor.getContent()
87 // get the content
88 str = tinyContent
89 str = str.replace(/<*.p> /gi, "");
90 // remove empty paragraphs
91 str = str.replace(/<*.div>/gi, "");
92 // remove any divs
93 str = str.replace(/<*.span>/gi, "");
94 // remove any spans left over
95 console.log(str)
96 currentEditor.setContent(str);
97 // set the content to this new text
98 tinymce.activeEditor.execCommand('SearchReplace')
99
100
101
102
103
104
105
106 //var assss = tesss.currentEditor.getContent()
107 //console.log(assss)
108
109
110 /*
111 str ='<div><span><p><Hello this is a test</p></span><div>'
112 console.log (str)
113 str = str.replace(/<*.em>/gi, "");
114 str = str.replace(/<*.div>/gi, "");
115 str = str.replace(/<*.span>/gi, "");
116 console.log(str)
117 //str='this string has <i>html</i> code i want to<b> remove</b><br>Link Number 1 -><a href="http://www.google.com">Google</a><br><p>Now back to normal text and stuff</p>';
118 str=str.replace(/<br>/gi, "\n");
119 str=str.replace(/<p.*>/gi, "\n");
120 str=str.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 (Link->$1) ");
121 str=str.replace(/<(?:.|\s)*?>/g, "");
122 console.log(str)
123 currentEditor.setContent(str);
124
125 */
126
127 //$('tinyMCE.get("tinymce.mce-content-body").setContent("<p>Test</p>"))')
128 //tinyMCE.activeEditor.setContent("<p>TEST</p>")
129 // console.log("Did we even get here")
130}
131
132/**
133 * Open a dialog window, set the size and content of the dialog
134 *
135 * @param {string} modalType - The switch value for which modal to open.
136 * @param {object} dialogData - A {object} that is used to pass data and properties to the modal.
137 */
138window.canvasExtension.runDialog = function(modalType, dialogData) {
139 // default values for dialog
140 var dWidth = 1000;
141 var dHeight = $(window).height();
142 var dPosition = "";
143 var dTitle = "";
144 var dialogHtml = "";
145
146 // setup for different types of dialogs
147 switch (modalType) {
148
149 case "RemoveAssignmentDates":
150 dialogHtml += "<p class='text-center'>Remove all of the assignment dates for this course (id: " + window.currentCourse + " )?</p>"
151 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeAssignmentDates();'>Yes, delete assignment dates</a></p>";
152 dWidth = 400;
153 dHeight = 300;
154 dTitle = "Remove assignment dates";
155 break;
156
157 case "OutcomeRemoveAssignmentDates":
158 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " assignments updated.</p>";
159 dWidth = 400;
160 dHeight = 300;
161 dTitle = "Assignment dates removed";
162 break;
163
164 case "RemoveEmptyModules":
165 dialogHtml += "<p class='text-center'>Delete all <strong>empty</strong> modules for this course (id: " + window.currentCourse + " )?</p>";
166 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.confirmRemoveEmptyModules();'>Yes, find empty modules</a></p>";
167 dialogHtml += "<p class='text-center'>Delete all <strong>empty</strong> assignment groups for this course (id: " + window.currentCourse + " )?</p>";
168 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.confirmRemoveEmptyAssignmentGroups();'>Yes, find empty assignment groups</a></p>";
169 dWidth = 450;
170 dHeight = 350;
171 dTitle = "Remove empty modules and assignment groups";
172 break;
173
174 case "ConfirmRemoveEmptyModule":
175 if (dialogData["modules"].length > 0) {
176 dialogHtml += "<p class='text-center'>The following modules are empty:</p>";
177 dialogHtml += "<ul>";
178 $.each(dialogData["modules"], function(i, mItem) {
179 dialogHtml += "<li>" + mItem.id + " - " + mItem.name + "</li>";
180 });
181 dialogHtml += "</ul>";
182 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeEmptyModules();'>REMOVE THESE MODULES</a></p>";
183 } else {
184 dialogHtml += "<p>There are no empty modules to remove.</p>";
185 }
186 dWidth = 400;
187 dHeight = 500;
188 dTitle = "Remove empty modules";
189 break;
190
191
192 case "ConfirmRemoveEmptyAssignmentGroups":
193 if (dialogData["assignment_groups"].length > 0) {
194 dialogHtml += "<p class='text-center'>The following assignment groups are empty:</p>";
195 dialogHtml += "<ul>";
196 $.each(dialogData["assignment_groups"], function(i, gItem) {
197 dialogHtml += "<li>" + gItem.id + " - " + gItem.name + "</li>";
198 });
199 dialogHtml += "</ul>";
200 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeEmptyAssignmentGroups();'>REMOVE THESE ASSIGNMENT GROUPS</a></p>";
201 } else {
202 dialogHtml += "<p>There are no empty assignment groups to remove.</p>";
203 }
204 dWidth = 400;
205 dHeight = 500;
206 dTitle = "Remove empty assignment groups";
207 break;
208
209 case "OutcomeRemoveEmptyModules":
210 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " empty modules have been removed.</p>";
211 dialogHtml += "<p class='text-center'>Please refresh the modules page to see the updates.</p>";
212 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
213 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
214 dWidth = 400;
215 dHeight = 450;
216 dTitle += "Empty modules removed";
217 break;
218
219 case "OutcomeRemoveEmptyAssignmentGroups":
220 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " empty assignment groups have been removed.</p>";
221 dialogHtml += "<p class='text-center'>Please refresh the assignments page to see the updates.</p>";
222 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
223 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
224 dWidth = 400;
225 dHeight = 450;
226 dTitle += "Empty assignment groups removed";
227 break;
228
229 case "EmptyItems":
230 dialogHtml += "<p><em>Note: You will have to refresh the Modules page after any removals to see updates.</em></p>";
231 dialogHtml += "<p>The following pages are empty (may take a while to load):</p>";
232 dialogHtml += "<table id='emptyPageList' class='table'><thead><tr><th>id</th><th>type</th><th>title</th><th>link</th><th>delete?</th></tr></thead><tbody></tbody></table>";
233 dialogHtml += "<div class='loading text-center'><img src='/images/ajax-reload-animated.gif'> Loading.</div>";
234 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
235 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
236 dWidth = 1000;
237 dTitle = "Remove empty pages/dicussions/assignments/quizzes";
238 break;
239
240 case "AddGroups":
241 if (dialogData["groupCategories"].length > 0) {
242 dialogHtml += "<p>Add group names on separate lines.</p>";
243 dialogHtml += "<p><strong>Group set</strong>: <select>";
244 $.each(dialogData["groupCategories"], function(i, gItem) {
245 dialogHtml += "<option value='" + gItem.id + "'>" + gItem.name + "</option>";
246 });
247 dialogHtml += "</select></p>";
248 dialogHtml += "<p class='text-center'><textarea style='width: 90%; height: 100px;'></textarea></p>";
249 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.canvasExtension.addGroups($(window.canvasExtension.dialogId+\" select option:selected\").val());'>Add groups</a></p>";
250 } else {
251 dialogHtml += "<p>There are no Group Categories. Please add a group category from the People tab.</p>";
252 }
253 dWidth = 500;
254 dHeight = 500;
255 dTitle = "Add groups";
256 break;
257
258 case "OutcomeAddGroups":
259 if (dialogData["groupNames"].length > 0) {
260 dialogHtml += "<p class='text-center'>" + dialogData["groupNames"].length + " groups added.</p>";
261 dialogHtml += "<p>" + dialogData["groupNames"].join(", ") + "</p>";
262 } else {
263 dialogHtml += "<p>No groups added.</p>"
264 }
265 dWidth = 400;
266 dHeight = 300;
267 dTitle = "Added groups";
268 break;
269
270 case "ManageGradeBookColumns":
271 dialogHtml += "<table id='emptyPageList' class='table'><thead><tr><th>title</th><th>hidden</th><th>teacher_notes</th><th>update?</th><th>delete?</th></tr></thead><tbody>";
272 if(window.canvasExtension.gradeBookColumns.length > 0){
273 $.each(window.canvasExtension.gradeBookColumns, function(i, gItem){
274 console.log(gItem);
275 dialogHtml += "<tr>";
276 dialogHtml += "<td><input class='gradebookcolumn_title' type='text' value='"+gItem.title+"'></input></td>";
277 dialogHtml += (gItem.hidden) ? "<td><input type='checkbox' class='gradebookcolumn_hidden' checked='checked'></input></td>" : "<td><input type='checkbox' class='gradebookcolumn_hidden'></input></td>";
278 dialogHtml += (gItem.teacher_notes) ? "<td><input type='checkbox' class='gradebookcolumn_teacher_notes' checked='checked'></input></td>" : "<td><input type='checkbox' class='gradebookcolumn_teacher_notes'></input></td>";
279 dialogHtml += "<td><a class='btn btn-success' onClick='window.canvasExtension.updateGradeBookColumn($(this), "+gItem.id+")'><i class='icon-refresh'> </i></a></td>";
280 dialogHtml += "<td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteGradeBookColumn($(this), "+gItem.id+");'><i class='icon-trash'> </i></a></td>";
281 dialogHtml += "</tr>";
282 });
283 }else{
284 dialogHtml += "<tr><td colspan='5'><p class='text-center'>There are no custom gradebook columns in this unit.</p></td></tr>";
285 }
286 dialogHtml += "</tbody></table>";
287 dialogHtml += "<hr/>";
288 dialogHtml += "<div id='addNewGradeBookColumn'>";
289 dialogHtml += "<p><strong>Add new gradebook column</strong></p>";
290 dialogHtml += "<p><strong>Title:</strong> <input class='gradebookcolumn_title' type='text'></input>";
291 dialogHtml += " <input type='checkbox' class='gradebookcolumn_hidden'></input> <strong>Hidden?</strong> ";
292 dialogHtml += " <input type='checkbox' class='gradebookcolumn_teacher_notes' checked='checked'><strong>Teacher notes?</strong> ";
293 dialogHtml += " <a class='btn btn-warning' onClick='window.canvasExtension.addGradeBookColumn();'>Add column</a></p>";
294 dialogHtml += "</div>"
295 dWidth = 800;
296 dTitle = "Manage gradebook columns";
297 break;
298
299
300 case "Message":
301 dialogHtml += dialogData["message"];
302 dWidth = 400;
303 dHeight = 300;
304 dTitle = dialogData["title"];
305 break;
306
307 default:
308 //nothing
309 }
310
311 //set dialog properties, and open the dialog window
312 window.canvasExtension.dialog.html("");
313 window.canvasExtension.dialog.append(dialogHtml);
314 // have to set the title in a few ways, the title doesn't change after the first time it runs
315 window.canvasExtension.dialog.attr("title", dTitle);
316 $('.ui-dialog-title', window.canvasExtension.dialog).html(dTitle);
317 window.canvasExtension.dialog.dialog({
318 "title": dTitle,
319 buttons: [{ text: "Close", click: function() { $(this).dialog("close"); } }]
320 });
321 window.canvasExtension.dialog.dialog("option", "width", dWidth);
322 window.canvasExtension.dialog.dialog("option", "height", dHeight);
323 window.canvasExtension.dialog.dialog("option", "position", dPosition);
324}
325
326
327
328// Expand all modules/assignments
329window.canvasExtension.contractAll = function() {
330 $('.ig-header-title.collapse_module_link:visible, .element_toggler[aria-expanded="true"]:visible').click();
331 $('.item-group-container .item-group-condensed, .ig-header').attr('style', 'padding: 0;').addClass('contractedExpanderGroups');
332 $('.item-group-container .ig-header button').attr('style', 'padding: 0 5px').addClass('contractedExpanderGroups');
333 //$('.ig-header-title, .expand_module_link').attr('style', 'margin: 0;');
334}
335
336// Contract all modules/assignments
337window.canvasExtension.expandAll = function() {
338 $('.ig-header-title.expand_module_link:visible, .element_toggler[aria-expanded="false"]:visible').click();
339 $('.contractedExpanderGroups').attr('style', '').removeClass('contractedExpanderGroups');
340}
341
342// publish all items on page
343window.canvasExtension.publishAll = function() {
344 //publish pages
345 $('#context_modules_sortable_container .context_module_item .ig-admin span[role="button"] > i').each(function() {
346 if ($(this).hasClass("icon-unpublish")) {
347 $(this).parent().trigger("click");
348 }
349 });
350 //publish modules
351 $('#context_modules_sortable_container div.ig-header > .ig-header-admin span[role="button"] > i').each(function() {
352 if ($(this).hasClass("icon-unpublish")) {
353 $(this).parent().trigger("click");
354 }
355 });
356}
357
358// Unpublish all items on page
359window.canvasExtension.unpublishAll = function() {
360 //unpublish pages
361 $('#context_modules_sortable_container .context_module_item .ig-admin span[role="button"] > i').each(function() {
362 if ($(this).hasClass("icon-publish")) {
363 $(this).parent().trigger("click");
364 }
365 });
366 //unpublish modules
367 $('#context_modules_sortable_container div.ig-header > .ig-header-admin span[role="button"] > i').each(function() {
368 if ($(this).hasClass("icon-publish")) {
369 $(this).parent().trigger("click");
370 }
371 });
372}
373
374// Set up page dialog
375window.canvasExtension.setupEmptyItems = function() {
376 window.canvasExtension.runDialog("EmptyItems");
377 window.canvasExtension.getEmptyItems();
378}
379
380// list all coueses in an account
381window.canvasExtension.getEmptyItems = function() {
382 //reset variables
383 window.canvasExtension.allItems = [];
384 window.canvasExtension.allItemsAjax = [];
385 // LIST ALL ITEMS
386 window.canvasExtension.listItemsFromCourse(
387 ["Page", "Assignment", "Discussion", "Quiz"], // types of search
388 { "Page": 1, "Assignment": 1, "Discussion": 1, "Quiz": 1 }, // type paging counters
389 { "Page": false, "Assignment": false, "Discussion": false, "Quiz": false }, // type done yet?
390 window.canvasExtension.allItems, // results array for all items
391 window.canvasExtension.allItemsAjax, // array for all ajax objs
392 window.canvasExtension.resultsEmptyItems // callback
393 );
394}
395
396window.canvasExtension.resultsEmptyItems = function() {
397 $(window.canvasExtension.dialogId + " .loading").remove();
398 $.each(window.canvasExtension.allItems, function(i, item) {
399 switch (item.type) {
400 case "Page":
401 if (!item.body) {
402 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.page_id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.url + "\")'><i class='icon-trash'> </i></a></td></p>");
403 }
404 break;
405 case "Assignment":
406 if (!item.description) {
407 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.name + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
408 }
409 break;
410 case "Discussion":
411 if (!item.message) {
412 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
413 }
414 break;
415 case "Quiz":
416 if (!item.description && item.question_count <= 0) {
417 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
418 }
419 break;
420 default:
421 }
422 });
423}
424
425/**
426 * Confirm the deletion of an item:
427 * Change the button that was pressed into a confirmation button, that when
428 * pressed, will trigger a function to remove the item.
429 *
430 * @param {$element} element - The jQuery element that triggered the call
431 * @param {string} type - The Canvas 'type' of the item, i.e. Page, Assignment, Discussion, Quiz
432 * @param {string} id - The id of the Canvas item
433 */
434window.canvasExtension.confirmDeleteItem = function(element, type, id) {
435 // set up the confirmation button
436 var confirmElement = "<a class='btn btn-danger' onClick='window.canvasExtension.removeItem(\"" + type + "\",\"" + id + "\");$(this).closest(\"tr\").remove();'>Are you sure?</a>";
437 // replace the @param element with the confirmation button
438 $(element).replaceWith(confirmElement);
439}
440
441
442/**
443 * Remove an item from the current course
444 *
445 * @param {string} type - The Canvas 'type' of the item, i.e. Page, Assignment, Discussion, Quiz
446 * @param {string} id - The id of the Canvas item
447 */
448window.canvasExtension.removeItem = function(type, id) {
449 var removeURL = "";
450 // generate the ajax URL that'll remove the item
451 switch (type) {
452 case "Page":
453 removeURL = "/api/v1/courses/" + window.currentCourse + "/pages/" + id
454 break;
455 case "Assignment":
456 removeURL = "/api/v1/courses/" + window.currentCourse + "/assignments/" + id
457 break;
458 case "Discussion":
459 removeURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics/" + id
460 break;
461 case "Quiz":
462 removeURL = "/api/v1/courses/" + window.currentCourse + "/quizzes/" + id
463 break;
464 default:
465 //ignore
466 }
467 // remove the item
468 $.ajax({
469 type: "DELETE",
470 url: removeURL,
471 dataType: "json",
472 headers: {
473 'Accept': 'application/json',
474 'Content-Type': 'application/json'
475 },
476 success: function(data, textStatus, xhr) {
477 console.log(textStatus, xhr.status, data);
478 },
479 error: function(xhr, textStatus, errorThrown) {
480 console.log("error: " + errorThrown);
481 }
482 });
483}
484
485/**
486 * Set up the Add Groups dialog:
487 * Get the current set of group categories, and pass them to the AddGroups dialog
488 * to use.
489 *
490 */
491window.canvasExtension.setupAddGroups = function() {
492 $.getJSON("/api/v1/courses/" + window.currentCourse + "/group_categories", function(groupCategoryData) {
493 var groupCategories = [];
494 $.each(groupCategoryData, function(i, groupCategory) {
495 groupCategories.push({
496 "id": groupCategory.id,
497 "name": groupCategory.name
498 });
499 });
500 window.canvasExtension.runDialog("AddGroups", { "groupCategories": groupCategories });
501 });
502}
503
504
505/**
506 * Add the groups from the text entred, to the course
507 *
508 * @param {string} groupCategory - The id of the group category to add the groups to.
509 */
510window.canvasExtension.addGroups = function(groupCategory) {
511 var groupNames = [];
512 // read the text area, split each new line into a string for a new group name
513 $.each($(window.canvasExtension.dialogId + ' textarea').attr('value').split("\n"), function() {
514 var groupId = this.trim();
515 if (groupId != "") groupNames.push(groupId);
516 });
517 // create the groups under the @groupCategory
518 $.each(groupNames, function(g, groupName) {
519 $.ajax({
520 type: "POST",
521 url: "/api/v1/group_categories/" + groupCategory + "/groups",
522 dataType: "json",
523 headers: {
524 'Accept': 'application/json',
525 'Content-Type': 'application/json'
526 },
527 data: '{"name":"' + groupName + '"}',
528 success: function(data, textStatus, xhr) {
529 console.log(textStatus, xhr.status, data);
530 },
531 error: function(xhr, textStatus, errorThrown) {
532 console.log("error: " + errorThrown);
533 }
534 });
535 });
536 // run the outcome dialog, returning the list of group names
537 window.canvasExtension.runDialog("OutcomeAddGroups", { "groupNames": groupNames });
538}
539
540
541/**
542 * Confirm the removal of all of the empty modules:
543 * Generate a list of empty modules, and send them to the confirmation dialog.
544 *
545 */
546window.canvasExtension.confirmRemoveEmptyModules = function() {
547 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
548 // search for modules in the current course, check to see if they are empty
549 $.getJSON("/api/v1/courses/" + window.currentCourse + "/modules?include=items&per_page=100", function(moduleData) {
550 var modulesForRemoval = [];
551 $.each(moduleData, function(i, mItem) {
552 if (mItem.items.length > 0) {
553 // ignore - not empty
554 } else {
555 modulesForRemoval.push(mItem);
556 }
557 });
558 // run the confirmation dialog
559 window.canvasExtension.runDialog("ConfirmRemoveEmptyModule", { "modules": modulesForRemoval });
560 });
561}
562
563/**
564 * Confirm the removal of all of the empty assignment groups:
565 * Generate a list of empty assignment groups, and send them to the confirmation dialog.
566 *
567 */
568window.canvasExtension.confirmRemoveEmptyAssignmentGroups = function() {
569 // search for assignment_groups in the current course, check to see if they are empty
570 $.getJSON("/api/v1/courses/" + window.currentCourse + "/assignment_groups?include=assignments&per_page=100", function(groupData) {
571 console.log(groupData);
572 var assignmentGroupsForRemoval = [];
573 $.each(groupData, function(i, gItem) {
574 if (gItem.assignments.length > 0) {
575 // ignore - not empty
576 } else {
577 assignmentGroupsForRemoval.push(gItem);
578 }
579 });
580 // run the confirmation dialog
581 window.canvasExtension.runDialog("ConfirmRemoveEmptyAssignmentGroups", { "assignment_groups": assignmentGroupsForRemoval });
582 });
583}
584
585/**
586 * Remove the empty modules from the course
587 *
588 */
589window.canvasExtension.removeEmptyModules = function() {
590 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
591 // search all of the modules of the current course
592 $.getJSON("/api/v1/courses/" + window.currentCourse + "/modules?include=items&per_page=100", function(moduleData) {
593 var mCount = 0;
594 $.each(moduleData, function(i, mItem) {
595 if (mItem.items.length > 0) {
596 // ignore - not empty
597 } else {
598 mCount++;
599 // delete the empty module
600 $.ajax({
601 type: "DELETE",
602 url: "/api/v1/courses/" + window.currentCourse + "/modules/" + mItem.id,
603 dataType: "json",
604 headers: {
605 'Accept': 'application/json',
606 'Content-Type': 'application/json'
607 },
608 success: function(data, textStatus, xhr) {
609 console.log(textStatus, xhr.status, data);
610 },
611 error: function(xhr, textStatus, errorThrown) {
612 console.log("error: " + errorThrown);
613 }
614 });
615 }
616 });
617 // show the outcome dialog, with a count of the number of modules removed.
618 window.canvasExtension.runDialog("OutcomeRemoveEmptyModules", { "number": mCount });
619 });
620}
621
622/**
623 * Remove the empty assignment groups from the course
624 *
625 */
626window.canvasExtension.removeEmptyAssignmentGroups = function() {
627 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
628 // search all of the modules of the current course
629 $.getJSON("/api/v1/courses/" + window.currentCourse + "/assignment_groups?include=assignments&per_page=100", function(assignmentGroupData) {
630 var gCount = 0;
631 $.each(assignmentGroupData, function(i, gItem) {
632 if (gItem.assignments.length > 0) {
633 // ignore - not empty
634 } else {
635 gCount++;
636 // delete the empty module
637 $.ajax({
638 type: "DELETE",
639 url: "/api/v1/courses/" + window.currentCourse + "/assignment_groups/" + gItem.id,
640 dataType: "json",
641 headers: {
642 'Accept': 'application/json',
643 'Content-Type': 'application/json'
644 },
645 success: function(data, textStatus, xhr) {
646 console.log(textStatus, xhr.status, data);
647 },
648 error: function(xhr, textStatus, errorThrown) {
649 console.log("error: " + errorThrown);
650 }
651 });
652 }
653 });
654 // show the outcome dialog, with a count of the number of modules removed.
655 window.canvasExtension.runDialog("OutcomeRemoveEmptyAssignmentGroups", { "number": gCount });
656 });
657}
658
659
660/**
661 * Remove dates from Assignment pages
662 *
663 */
664window.canvasExtension.removeAssignmentDates = function() {
665 // get all of the assignments in the courses
666 $.ajax({
667 type: "get",
668 url: "/api/v1/courses/" + window.currentCourse + "/assignments?per_page=100",
669 crossDomain: true,
670 cache: false,
671 dataType: "json",
672 contentType: "application/json; charset=UTF-8",
673 success: function(data, textStatus, xhr) {
674 for (var i = 0; i < data.length; i++) {
675 // remove the due date, and start/end dates for each assignment
676 $.ajax({
677 type: "PUT",
678 url: "/api/v1/courses/" + window.currentCourse + "/assignments/" + data[i].id,
679 dataType: "json",
680 headers: {
681 'Accept': 'application/json',
682 'Content-Type': 'application/json'
683 },
684 data: '{"assignment":{"due_at":"","lock_at":"","unlock_at":""}}',
685 success: function(data, textStatus, xhr) {
686 console.log(textStatus, xhr.status, data);
687 },
688 error: function(xhr, textStatus, errorThrown) {
689 console.log("error: " + errorThrown);
690 }
691 });
692 }
693 // show the outcome dialog, send then number of assignments that were updated
694 window.canvasExtension.runDialog("OutcomeRemoveAssignmentDates", { "number": data.length });
695 },
696 error: function(xhr, textStatus, errorThrown) {
697 console.log("error: " + errorThrown);
698 }
699 });
700}
701
702/**
703 * LIST ALL ITEMS FROM COURSE BY TYPE
704 *
705 *
706 * @param {array} itemTypes - set of item types, i.e. ["Page", "Assignment", "Discussion", "Quiz"]
707 * @param {object} itemTypesPageCount - object with page counter matching types
708 * @param {object} resultsByType - object with resutls by type
709 * @param {global array} itemResults - array for item results
710 * @param {global array} itemsResultsAjax - array for ajax calls
711 * @param {requestCallback} callback - callback function, this runs after all of the items have been retrieved
712 */
713window.canvasExtension.listItemsFromCourse = function(itemTypes, itemTypesPageCount, resultsByType, itemResults, itemsResultsAjax, callback) {
714 $.each(itemTypes, function(i, itemType) {
715 var itemType = itemType;
716 var itemTypeURL = "";
717 var itemURL = "";
718 var itemIdOn = "";
719
720 // get URLs for item calls. Canvas is limited to 100 items per 'page', so listItemsFromCourse may be called multiple times
721 switch (itemType) {
722 case "Page":
723 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/pages?sort=title&page=" + itemTypesPageCount[itemType] + "&per_page=100"
724 itemURL = "/api/v1/courses/" + window.currentCourse + "/pages/"
725 itemIdOn = 'url'
726 break;
727 case "Assignment":
728 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/assignments?page=" + itemTypesPageCount[itemType] + "&per_page=100"
729 itemURL = "/api/v1/courses/" + window.currentCourse + "/assignments/"
730 itemIdOn = 'id'
731 break;
732 case "Discussion":
733 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics?page=" + itemTypesPageCount[itemType] + "&per_page=100"
734 itemURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics/"
735 itemIdOn = 'id'
736 break;
737 case "Quiz":
738 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/quizzes?page=" + itemTypesPageCount[itemType] + "&per_page=100"
739 itemURL = "/api/v1/courses/" + window.currentCourse + "/quizzes/"
740 itemIdOn = 'id'
741 break;
742 default:
743 }
744
745 itemsResultsAjax.push(
746 $.ajax({
747 type: "GET",
748 url: itemTypeURL,
749 success: function(data, textStatus, xhr) {
750 $.each(data, function(t, tItem) {
751 itemsResultsAjax.push($.ajax({
752 type: "GET",
753 url: itemURL + tItem[itemIdOn],
754 success: function(data) {
755 data.type = itemType;
756 // add item to results
757 itemResults.push(data);
758 }
759 }));
760 });
761 // will throw out of loop if number of courses > 10000 -- if you have more than 10000 units, increase the pNum check
762 if (xhr.getResponseHeader('Link').indexOf('rel="next"') > 0 && itemTypesPageCount[itemType] < 100) {
763 itemTypesPageCount[itemType]++;
764 // get next page
765 // keep getting items, get next set for this item type
766 window.canvasExtension.listItemsFromCourse([itemType], itemTypesPageCount, resultsByType, itemResults, itemsResultsAjax, callback);
767 } else {
768 resultsByType[itemType] = true;
769 //check all items for all item types are done
770 var allTrue = true;
771 $.each(resultsByType, function(n, nDone) {
772 if (!nDone) allTrue = false;
773 });
774 // if they're all done, do results
775 if (allTrue) {
776 // when all the ajax is done, run the callback
777 $.when.apply(undefined, itemsResultsAjax).then(callback);
778 }
779 }
780 },
781 error: function(xhr, textStatus, errorThrown) {
782 console.log("error: " + errorThrown);
783 }
784 })
785 );
786 });
787}
788
789
790
791/**
792 * setupGradeBookColumns
793 */
794window.canvasExtension.setupGradeBookColumns = function(){
795 window.canvasExtension.listGradeBookColumns(function(data){
796 window.canvasExtension.gradeBookColumns = data;
797 window.canvasExtension.runDialog("ManageGradeBookColumns");
798 });
799}
800
801/**
802 * LIST - GET /api/v1/courses/:course_id/custom_gradebook_columns
803 * @param {function} callback
804 */
805window.canvasExtension.listGradeBookColumns = function(callback){
806 $.getJSON("/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns?include_hidden=true", function(data) {
807 callback(data);
808 //window.canvasExtension.newGradeBookColumn("New column", gradeBookColumns.length+1, false, true)
809 });
810}
811
812/**
813 * Confirm the deletion of an item:
814 * Change the button that was pressed into a confirmation button, that when
815 * pressed, will trigger a function to remove the item.
816 *
817 * @param {$element} element - The jQuery element that triggered the call
818 * @param {string} id - The id of the gradebook column
819 */
820window.canvasExtension.confirmDeleteGradeBookColumn = function(element, id){
821 // set up the confirmation button
822 var confirmElement = "<a class='btn btn-danger' onClick='window.canvasExtension.deleteGradeBookColumn(\"" + id + "\");$(this).closest(\"tr\").remove();'>Are you sure?</a>";
823 // replace the @param element with the confirmation button
824 $(element).replaceWith(confirmElement);
825}
826
827
828/**
829 * LIST - GET /api/v1/courses/:course_id/custom_gradebook_columns
830 * @param {function} callback
831 */
832window.canvasExtension.deleteGradeBookColumn = function(id){
833 // remove the gradebook column
834 $.ajax({
835 type: "DELETE",
836 url: "/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns/"+id,
837 dataType: "json",
838 headers: {
839 'Accept': 'application/json',
840 'Content-Type': 'application/json'
841 },
842 success: function(data, textStatus, xhr) {
843 console.log(textStatus, xhr.status, data);
844 window.canvasExtension.setupGradeBookColumns();
845 },
846 error: function(xhr, textStatus, errorThrown) {
847 console.log("error: " + errorThrown);
848 }
849 });
850}
851
852
853
854/**
855 * UPDATE - PUT /api/v1/courses/:course_id/custom_gradebook_columns/:id
856 * @param {$element} update button that called function
857 * @param {string} id of gradebook column
858 */
859window.canvasExtension.updateGradeBookColumn = function(element, id){
860 var column_title = $(element).closest('tr').find('.gradebookcolumn_title').attr('value');
861 var column_hidden = ($(element).closest('tr').find('.gradebookcolumn_hidden').attr('checked')) ? true : false;
862 var column_teacher_notes = ($(element).closest('tr').find('.gradebookcolumn_teacher_notes').attr('checked')) ? true : false;
863 console.log("column_title", column_title, "column_hidden", column_hidden, "column_teacher_notes", column_teacher_notes);
864 $.ajax({
865 type: "PUT",
866 url: "/api/v1/courses/" + window.currentCourse + "/custom_gradebook_columns/" + id,
867 dataType: "json",
868 headers: {
869 'Accept': 'application/json',
870 'Content-Type': 'application/json'
871 },
872 data: '{"column": {"title": "'+column_title+'", "hidden": "'+column_hidden+'", "teacher_notes": "'+column_teacher_notes+'"}}',
873 success: function(data, textStatus, xhr) {
874 console.log(textStatus, xhr.status, data);
875 window.canvasExtension.setupGradeBookColumns();
876 },
877 error: function(xhr, textStatus, errorThrown) {
878 console.log("error: " + errorThrown);
879 }
880 });
881}
882
883
884/**
885 * Add gradebook column
886 */
887window.canvasExtension.addGradeBookColumn = function(){
888 var column_title = $(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_title").attr('value');
889 var column_position = window.canvasExtension.gradeBookColumns.length+1;
890 var column_hidden = ($(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_hidden").attr('checked')) ? true : false;
891 var column_teacher_notes = ($(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_teacher_notes").attr('checked')) ? true : false;
892 window.canvasExtension.createGradeBookColumn(column_title, column_position, column_hidden, column_teacher_notes, window.canvasExtension.setupGradeBookColumns);
893}
894
895
896/**
897 * NEW COLUMN - POST /api/v1/courses/:course_id/custom_gradebook_columns
898 * @param {Required string} column_title - no description
899 * @param {integer} column_position - The position of the column relative to other custom columns
900 * @param {boolean} column_hidden - Hidden columns are not displayed in the gradebook
901 * @param {boolean} column_teacher_notes - Set this if the column is created by a teacher. The gradebook only supports one teacher_notes column.
902 * @param {function} callback
903 */
904window.canvasExtension.createGradeBookColumn = function(column_title, column_position, column_hidden, column_teacher_notes, callback){
905 $.ajax({
906 type: "POST",
907 url: "/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns",
908 dataType: "json",
909 headers: {
910 'Accept': 'application/json',
911 'Content-Type': 'application/json'
912 },
913 data: '{"column":{"title": "'+column_title+'", "position": '+column_position+', "hidden": '+column_hidden+',"teacher_notes": '+column_teacher_notes+'}}',
914 success: function(data, textStatus, xhr) {
915 console.log(textStatus, xhr.status, data);
916 callback();
917 },
918 error: function(xhr, textStatus, errorThrown) {
919 console.log("error: " + errorThrown);
920 }
921 });
922}
923
924
925
926
927// ------------------ WIP::COURSES -----------------
928
929
930window.canvasExtension.allCourses = [];
931
932// list all coueses in an account
933window.canvasExtension.listAllCourses = function() {
934 window.canvasExtension.allCourses = [];
935 var nextPage = 1;
936 window.canvasExtension.listNextCourses(nextPage);
937}
938
939window.canvasExtension.listNextCourses = function(pNum) {
940 $.ajax({
941 type: "GET",
942 url: "/api/v1/accounts/1/courses?page=" + pNum + "&per_page=100",
943 dataType: "json",
944 headers: {
945 'Accept': 'application/json',
946 'Content-Type': 'application/json'
947 },
948 success: function(data, textStatus, xhr) {
949 //console.log(xhr.getResponseHeader('Link'));
950 $.each(data, function(i, tCourse) {
951 window.canvasExtension.allCourses.push({
952 "name": tCourse.name,
953 "id": tCourse.id
954 });
955 //$(window.canvasExtension.dialogId+" #courseList tbody").append('<tr><td>'+tCourse.id+'</td><td>'+tCourse.name+'</td></tr>');
956 });
957 //will throw out of loop if number of courses > 10000 -- if you have more than 10000 units, increase the pNum check
958 if (xhr.getResponseHeader('Link').indexOf('rel="next"') > 0 && pNum < 100) {
959 pNum++;
960 window.canvasExtension.listNextCourses(pNum);
961 } else {
962 window.canvasExtension.addCourseResults();
963 }
964 },
965 error: function(xhr, textStatus, errorThrown) {
966 console.log("error: " + errorThrown);
967 }
968 });
969}
970
971window.canvasExtension.addCourseResults = function() {
972 console.log(window.canvasExtension.allCourses);
973}
974
975
976//---- RUN THE INIT ------------------------------
977
978window.canvasExtension.initCanvasExtensionMenu();