| 1 | efrain | 1 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 2 | //
 | 
        
           |  |  | 3 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 4 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 5 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 6 | // (at your option) any later version.
 | 
        
           |  |  | 7 | //
 | 
        
           |  |  | 8 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 11 | // GNU General Public License for more details.
 | 
        
           |  |  | 12 | //
 | 
        
           |  |  | 13 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 14 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 15 |   | 
        
           |  |  | 16 | /**
 | 
        
           |  |  | 17 |  * Parse the response from the navblock ajax page and render the correct DOM
 | 
        
           |  |  | 18 |  * structure for the tree from it.
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @module     block_navigation/ajax_response_renderer
 | 
        
           |  |  | 21 |  * @copyright  2015 John Okely <john@moodle.com>
 | 
        
           |  |  | 22 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 | define([
 | 
        
           |  |  | 25 |     'jquery',
 | 
        
           |  |  | 26 |     'core/templates',
 | 
        
           |  |  | 27 |     'core/notification',
 | 
        
           |  |  | 28 |     'core/url',
 | 
        
           |  |  | 29 |     'core/aria',
 | 
        
           |  |  | 30 | ], function(
 | 
        
           |  |  | 31 |     $,
 | 
        
           |  |  | 32 |     Templates,
 | 
        
           |  |  | 33 |     Notification,
 | 
        
           |  |  | 34 |     Url,
 | 
        
           |  |  | 35 |     Aria
 | 
        
           |  |  | 36 | ) {
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 |     // Mappings for the different types of nodes coming from the navigation.
 | 
        
           |  |  | 39 |     // Copied from lib/navigationlib.php navigation_node constants.
 | 
        
           |  |  | 40 |     var NODETYPE = {
 | 
        
           |  |  | 41 |         // @type int Activity (course module) = 40.
 | 
        
           |  |  | 42 |         ACTIVITY: 40,
 | 
        
           |  |  | 43 |         // @type int Resource (course module = 50.
 | 
        
           |  |  | 44 |         RESOURCE: 50,
 | 
        
           |  |  | 45 |     };
 | 
        
           |  |  | 46 |   | 
        
           |  |  | 47 |     /**
 | 
        
           |  |  | 48 |      * Build DOM.
 | 
        
           |  |  | 49 |      *
 | 
        
           |  |  | 50 |      * @method buildDOM
 | 
        
           |  |  | 51 |      * @param {Object} rootElement the root element of DOM.
 | 
        
           |  |  | 52 |      * @param {object} nodes jquery object representing the nodes to be build.
 | 
        
           |  |  | 53 |      */
 | 
        
           |  |  | 54 |     function buildDOM(rootElement, nodes) {
 | 
        
           |  |  | 55 |         var ul = $('<ul></ul>');
 | 
        
           |  |  | 56 |         ul.attr('role', 'group');
 | 
        
           |  |  | 57 |         Aria.hide(ul);
 | 
        
           |  |  | 58 |   | 
        
           |  |  | 59 |         $.each(nodes, function(index, node) {
 | 
        
           |  |  | 60 |             if (typeof node !== 'object') {
 | 
        
           |  |  | 61 |                 return;
 | 
        
           |  |  | 62 |             }
 | 
        
           |  |  | 63 |   | 
        
           |  |  | 64 |             var li = $('<li></li>');
 | 
        
           |  |  | 65 |             var p = $('<p></p>');
 | 
        
           |  |  | 66 |             var id = node.id || node.key + '_tree_item';
 | 
        
           |  |  | 67 |             var icon = null;
 | 
        
           |  |  | 68 |             var isBranch = (node.expandable || node.haschildren) ? true : false;
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 |             li.attr('role', 'treeitem');
 | 
        
           |  |  | 71 |             p.addClass('tree_item');
 | 
        
           |  |  | 72 |             p.attr('id', id);
 | 
        
           |  |  | 73 |             // Negative tab index to allow it to receive focus.
 | 
        
           |  |  | 74 |             p.attr('tabindex', '-1');
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 |             if (node.requiresajaxloading) {
 | 
        
           |  |  | 77 |                 li.attr('data-requires-ajax', true);
 | 
        
           |  |  | 78 |                 li.attr('data-node-id', node.id);
 | 
        
           |  |  | 79 |                 li.attr('data-node-key', node.key);
 | 
        
           |  |  | 80 |                 li.attr('data-node-type', node.type);
 | 
        
           |  |  | 81 |             }
 | 
        
           |  |  | 82 |   | 
        
           |  |  | 83 |             if (isBranch) {
 | 
        
           |  |  | 84 |                 li.addClass('collapsed contains_branch');
 | 
        
           |  |  | 85 |                 li.attr('aria-expanded', false);
 | 
        
           |  |  | 86 |                 p.addClass('branch');
 | 
        
           |  |  | 87 |             }
 | 
        
           |  |  | 88 |   | 
        
           |  |  | 89 |             var eleToAddIcon = null;
 | 
        
           |  |  | 90 |             if (node.link) {
 | 
        
           |  |  | 91 |                 var link = $('<a title="' + node.title + '" href="' + node.link + '"></a>');
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |                 eleToAddIcon = link;
 | 
        
           |  |  | 94 |                 link.append('<span class="item-content-wrap">' + node.name + '</span>');
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |                 if (node.hidden) {
 | 
        
           |  |  | 97 |                     link.addClass('dimmed');
 | 
        
           |  |  | 98 |                 }
 | 
        
           |  |  | 99 |   | 
        
           |  |  | 100 |                 p.append(link);
 | 
        
           |  |  | 101 |             } else {
 | 
        
           |  |  | 102 |                 var span = $('<span></span>');
 | 
        
           |  |  | 103 |   | 
        
           |  |  | 104 |                 eleToAddIcon = span;
 | 
        
           |  |  | 105 |                 span.append('<span class="item-content-wrap">' + node.name + '</span>');
 | 
        
           |  |  | 106 |   | 
        
           |  |  | 107 |                 if (node.hidden) {
 | 
        
           |  |  | 108 |                     span.addClass('dimmed');
 | 
        
           |  |  | 109 |                 }
 | 
        
           |  |  | 110 |   | 
        
           |  |  | 111 |                 p.append(span);
 | 
        
           |  |  | 112 |             }
 | 
        
           |  |  | 113 |   | 
        
           |  |  | 114 |             if (node.icon && (!isBranch || node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE)) {
 | 
        
           |  |  | 115 |                 li.addClass('item_with_icon');
 | 
        
           |  |  | 116 |                 p.addClass('hasicon');
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 |                 if (node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE) {
 | 
        
           |  |  | 119 |                     icon = $('<img/>');
 | 
        
           |  |  | 120 |                     icon.attr('alt', node.icon.alt);
 | 
        
           |  |  | 121 |                     icon.attr('title', node.icon.title);
 | 
        
           |  |  | 122 |                     icon.attr('src', Url.imageUrl(node.icon.pix, node.icon.component));
 | 
        
           |  |  | 123 |                     $.each(node.icon.classes, function(index, className) {
 | 
        
           |  |  | 124 |                         icon.addClass(className);
 | 
        
           |  |  | 125 |                     });
 | 
        
           |  |  | 126 |                     eleToAddIcon.prepend(icon);
 | 
        
           |  |  | 127 |                 } else {
 | 
        
           |  |  | 128 |                     if (node.icon.component == 'moodle') {
 | 
        
           |  |  | 129 |                         node.icon.component = 'core';
 | 
        
           |  |  | 130 |                     }
 | 
        
           |  |  | 131 |                     Templates.renderPix(node.icon.pix, node.icon.component, node.icon.title).then(function(html) {
 | 
        
           |  |  | 132 |                         // Prepend.
 | 
        
           |  |  | 133 |                         eleToAddIcon.prepend(html);
 | 
        
           |  |  | 134 |                         return;
 | 
        
           |  |  | 135 |                     }).catch(Notification.exception);
 | 
        
           |  |  | 136 |                 }
 | 
        
           |  |  | 137 |             }
 | 
        
           |  |  | 138 |   | 
        
           |  |  | 139 |             li.append(p);
 | 
        
           |  |  | 140 |             ul.append(li);
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 |             if (node.children && node.children.length) {
 | 
        
           |  |  | 143 |                 buildDOM(li, node.children);
 | 
        
           |  |  | 144 |             } else if (isBranch && !node.requiresajaxloading) {
 | 
        
           |  |  | 145 |                 li.removeClass('contains_branch');
 | 
        
           |  |  | 146 |                 p.addClass('emptybranch');
 | 
        
           |  |  | 147 |             }
 | 
        
           |  |  | 148 |         });
 | 
        
           |  |  | 149 |   | 
        
           |  |  | 150 |         rootElement.append(ul);
 | 
        
           |  |  | 151 |         var id = rootElement.attr('id') + '_group';
 | 
        
           |  |  | 152 |         ul.attr('id', id);
 | 
        
           |  |  | 153 |         rootElement.attr('aria-owns', id);
 | 
        
           |  |  | 154 |         rootElement.attr('role', 'treeitem');
 | 
        
           |  |  | 155 |     }
 | 
        
           |  |  | 156 |   | 
        
           |  |  | 157 |     return {
 | 
        
           |  |  | 158 |         render: function(element, nodes) {
 | 
        
           |  |  | 159 |             // The first element of the response is the existing node so we start with processing the children.
 | 
        
           |  |  | 160 |             if (nodes.children && nodes.children.length) {
 | 
        
           |  |  | 161 |                 buildDOM(element, nodes.children);
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 |                 var item = element.children("[role='treeitem']").first();
 | 
        
           |  |  | 164 |                 var group = element.find('#' + item.attr('aria-owns'));
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 |                 item.attr('aria-expanded', true);
 | 
        
           |  |  | 167 |                 Aria.unhide(group);
 | 
        
           |  |  | 168 |             } else {
 | 
        
           |  |  | 169 |                 if (element.hasClass('contains_branch')) {
 | 
        
           |  |  | 170 |                     element.removeClass('contains_branch');
 | 
        
           |  |  | 171 |                     element.addClass('emptybranch');
 | 
        
           |  |  | 172 |                 }
 | 
        
           |  |  | 173 |             }
 | 
        
           |  |  | 174 |         }
 | 
        
           |  |  | 175 |     };
 | 
        
           |  |  | 176 | });
 |