const CourseWizard = { /** * Adds a new participating institute to the course. * @param id Stud.IP institute ID * @param name Full name * @param inputName name of the for input to generate * @param elClass desired CSS class name * @param elId ID of the target container to append to * @param otherInput name of other inputs to check * * (e.g. deputies if adding a lecturer) */ addParticipatingInst: function(id, name) { // Check if already set. if ($('input[name="participating[' + id + ']"]').length == 0) { var wrapper = $('
').addClass('institute'); $('#wizard-participating') .children('div.description') .removeClass('hidden-js'); var input = $('') .attr('type', 'hidden') .attr('name', 'participating[' + id + ']') .attr('id', id) .attr('value', '1'); var trash = $('') .attr('type', 'image') .attr('src', STUDIP.ASSETS_URL + 'images/icons/blue/trash.svg') .attr('name', 'remove_participating[' + id + ']') .attr('value', '1') .attr('onclick', "return STUDIP.CourseWizard.removeParticipatingInst('" + id + "')") .addClass('text-bottom') .css({ width: 16, height: 16 }); wrapper.append(input); var nametext = $('') .html(name) .text(); wrapper.append(nametext); wrapper.append(trash); $('#wizard-participating').append(wrapper); } }, /** * Remove a participating institute from the list. * @param id ID of the institute to remove * @returns {boolean} */ removeParticipatingInst: function(id) { var parent = $('input#' + id).parent(); var grandparent = parent.parent(); parent.remove(); if (grandparent.children('div').length == 0) { grandparent.children('div.description').addClass('hidden-js'); } return false; }, /** * Adds a new person to the course. * @param id Stud.IP user ID * @param name Full name * @param inputName name of the for input to generate * @param elClass desired CSS class name * @param elId ID of the target container to append to * @param otherInput name of other inputs to check * * (e.g. deputies if adding a lecturer) */ addPerson: function(id, name, inputName, elClass, elId, otherInput) { // Check if already set. if ($('input[name="' + inputName + '[' + id + ']"]').length == 0) { var wrapper = $('
').addClass(elClass); $('#' + elId) .children('div.description') .removeClass('hidden-js'); var input = $('') .attr('type', 'hidden') .attr('name', inputName + '[' + id + ']') .attr('id', id) .attr('value', '1'); var trash = $('') .attr('type', 'image') .attr('src', STUDIP.ASSETS_URL + 'images/icons/blue/trash.svg') .attr('name', 'remove_' + elClass + '[' + id + ']') .attr('value', '1') .attr('onclick', "return STUDIP.CourseWizard.removePerson('" + id + "')") .css({ width: 16, height: 16 }); wrapper.append(input); var nametext = $('') .html(name) .text(); wrapper.append(nametext); wrapper.append(trash); $('#' + elId).append(wrapper); // Remove as deputy if set. $('input[name="' + otherInput + '[' + id + ']"]') .parent() .remove(); } }, /** * Adds a new lecturer to the course. * @param id Stud.IP user ID * @param name Full name */ addLecturer: function(id, name) { CourseWizard.addPerson(id, name, 'lecturers', 'lecturer', 'wizard-lecturers', 'deputies'); // Add deputies if applicable. CourseWizard.addDefaultDeputies(id); }, /** * Adds a new deputy to the course. * @param id Stud.IP user ID * @param name Full name */ addDeputy: function(id, name) { CourseWizard.addPerson(id, name, 'deputies', 'deputy', 'wizard-deputies', 'lecturers'); }, addTutor: function(id, name) { CourseWizard.addPerson(id, name, 'tutors', 'tutor', 'wizard-tutors', 'lecturers'); }, /** * Adds the default deputies of given user to the course. * @param id Stud.IP user ID */ addDefaultDeputies: function(id) { var lecturerDiv = $('#wizard-lecturers'); if ($('input[name="deputy_id_parameter"]').length > 0 && lecturerDiv.data('default-enabled') == '1') { var params = 'step=' + $('input[name="step"]').val() + '&method=getDefaultDeputies' + '¶meter[]=' + id; $.ajax(lecturerDiv.data('ajax-url'), { data: params, success: function(data, status, xhr) { if (data.length > 0) { for (var i = 0; i < data.length; i++) { CourseWizard.addDeputy(data[i].id, data[i].name); } } } }); } }, /** * Remove a person (lecturer or deputy) from the list. * @param id ID of the person to remove * @returns {boolean} */ removePerson: function(id) { var parent = $('input#' + id).parent(); var grandparent = parent.parent(); parent.remove(); if (grandparent.children('div[class!="description"]').length == 0) { grandparent.children('div.description').addClass('hidden-js'); } return false; }, /** * Fetches the children of a given sem tree node. * @param node the ID of the parent. * @param assignable is the given node part of the * full sem tree or the tree of already * assigned nodes? * @returns {boolean} */ getTreeChildren: function(node, assignable) { var target = $('.' + (assignable ? 'sem-tree-' : 'sem-tree-assign-') + node); if (!target.hasClass('tree-loaded') && target.find('.tree-loading').length == 0) { var params = 'step=' + $('input[name="step"]').val() + '&method=getSemTreeLevel' + '¶meter[]=' + $('#' + node).attr('id'); $.ajax($('#studyareas').data('ajax-url'), { data: params, beforeSend: function(xhr, settings) { target.children('ul').append( $('
  • ').html( $('') .attr('src', STUDIP.ASSETS_URL + 'images/ajax-indicator-black.svg') .css('width', '16') .css('height', '16') ) ); }, success: function(data, status, xhr) { target.find('li.sem-tree-result').remove(); var items = $.parseJSON(data); target.find('.tree-loading').remove(); if (items.length > 0) { var list = target.children('ul'); for (var i = 0; i < items.length; i++) { list.append(CourseWizard.createTreeNode(items[i], assignable)); } } target.addClass('tree-loaded'); }, error: function(xhr, status, error) { alert(error); } }); } if (!target.hasClass('tree-open')) { target.removeClass('tree-closed').addClass('tree-open'); } else { target.removeClass('tree-open').addClass('tree-closed'); } var checkbox = target.children('input[id="' + node + '"]'); checkbox.prop('checked', !checkbox.prop('checked')); return false; }, /** * Search the sem tree for a given term and show all matching nodes. * @returns {boolean} */ searchTree: function() { var searchterm = $('#sem-tree-search').val(); if (searchterm != '') { var params = 'step=' + $('input[name="step"]').val() + '&method=searchSemTree' + '¶meter[]=' + searchterm; $.ajax($('#studyareas').data('ajax-url'), { data: params, beforeSend: function(xhr, settings) { $('#sem-tree-search-start') .parent() .append( $('') .attr('src', STUDIP.ASSETS_URL + 'images/ajax-indicator-black.svg') .attr('id', 'sem-tree-search-loading') .css('width', '16') .css('height', '16') ); CourseWizard.loadingOverlay($('div#studyareas ul.css-tree')); }, success: function(data, status, xhr) { $('#loading-overlay').remove(); $('#sem-tree-search-loading').remove(); var items = $.parseJSON(data); if (items.length > 0) { $('#sem-tree-search-reset') .removeClass('hidden-js') .css('display', ''); $('#studyareas li input[type="checkbox"]').prop('checked', false); $('#studyareas li') .not('.keep-node') .addClass('css-tree-hidden'); CourseWizard.buildPartialTree(items, true, ''); $('#sem-tree-assign-all').removeClass('hidden-js'); $('li.sem-tree-root input#root').prop('checked', true); } else { alert($('#studyareas').data('no-search-result')); } }, error: function(xhr, status, error) { alert(error); } }); } return false; }, /** * Reset a search and restore the "normal" sem tree view. * @returns {boolean} */ resetSearch: function() { $('li.css-tree-hidden').removeClass('css-tree-hidden'); $('#sem-tree-search-reset').addClass('hidden-js'); $('#sem-tree-search').val(''); $('.css-tree-hidden').removeClass('css-tree-hidden'); var notloaded = $('#studyareas li').not('.tree-loaded'); notloaded.children('input[type="checkbox"]').prop('checked', false); notloaded.children('ul').empty(); $('#sem-tree-assign-all').addClass('hidden-js'); $('input[name="searchterm"]').remove(); return false; }, /** * Build a partial sem tree, containing (or showing) only selected nodes. * @param items items to show in the resulting tree * @param assignable are the nodes part of the full * sem tree whose entries can be assigned? * @param source_node the single node that initiated the tree building, * useful for marking elements. * @returns {boolean} */ buildPartialTree: function(items, assignable, source_node) { if (assignable) { var classPrefix = 'sem-tree-'; } else { var classPrefix = 'sem-tree-assigned-'; } for (var i = 0; i < items.length; i++) { var parent = $('.' + classPrefix + items[i].parent); var node = $('.' + classPrefix + items[i].id); if (node.length == 0) { if (!assignable && source_node == items[i].id) { var selected = true; } else { var selected = false; } var node = CourseWizard.createTreeNode(items[i], assignable, selected); parent.children('ul').append(node); } else { node.removeClass('css-tree-hidden'); if (!assignable && items[i].id == source_node) { var input = $('') .attr('type', 'hidden') .attr('name', 'studyareas[]') .attr('value', items[i].id); node.children('ul').before(input); var unassign = $('') .attr('type', 'image') .attr('name', 'unassign[' + items[i].id + ']') .attr('src', STUDIP.ASSETS_URL + 'images/icons/blue/trash.svg') .attr('width', '16') .height('height', '16') .attr('onclick', "return STUDIP.CourseWizard.unassignNode('" + items[i].id + "')"); node.children('input[name="studyareas[]"]').before(unassign); } } node.children('input#' + items[i].id).prop('checked', true); if (items[i].assignable) { node.addClass('sem-tree-result'); } parent.children('input[id="' + items[i].parent + '"]').attr('checked', true); if (items[i].has_children) { CourseWizard.buildPartialTree(items[i].children, assignable, source_node); } } return false; }, /** * Creates a tree node element from given data. * @param values values for the node * @param assignable is the node part of the full * sem tree whose entries can be assigned? * @returns {*|jQuery} */ createTreeNode: function(values, assignable, selected) { // Node in "All study areas" tree. if (assignable) { var item = $('
  • ').addClass('sem-tree-' + values.id); var assign = $('') .attr('type', 'image') .attr('name', 'assign[' + values.id + ']') .attr('src', STUDIP.ASSETS_URL + 'images/icons/yellow/arr_2left.svg') .attr('width', '16') .height('height', '16') .attr('onclick', "return STUDIP.CourseWizard.assignNode('" + values.id + "')"); if (values.assignable) { item.append(assign); item.append(document.createTextNode(' ')); } if (values.has_children) { var input = $('') .attr('type', 'checkbox') .attr('id', values.id); var label = $('