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