MDL-62746 tag: Make forms in tag modals use proper BS classes
[moodle.git] / lib / amd / src / tag.js
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/>.
16 /**
17  * AJAX helper for the tag management page.
18  *
19  * @module     core/tag
20  * @package    core_tag
21  * @copyright  2015 Marina Glancy
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  * @since      3.0
24  */
25 define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/yui'],
26         function($, ajax, templates, notification, str, Y) {
27     return /** @alias module:core/tag */ {
29         /**
30          * Initialises tag index page.
31          *
32          * @method initTagindexPage
33          */
34         initTagindexPage: function() {
35             // Click handler for changing tag type.
36             $('body').delegate('.tagarea[data-ta] a[data-quickload=1]', 'click', function(e) {
37                 e.preventDefault();
38                 var target = $(this),
39                     query = target[0].search.replace(/^\?/, ''),
40                     tagarea = target.closest('.tagarea[data-ta]'),
41                     args = query.split('&').reduce(function(s, c) {
42                       var t = c.split('=');
43                       s[t[0]] = decodeURIComponent(t[1]);
44                       return s;
45                     }, {});
47                 var promises = ajax.call([{
48                     methodname: 'core_tag_get_tagindex',
49                     args: {tagindex: args}
50                 }], true);
52                 $.when.apply($, promises)
53                     .done(function(data) {
54                         templates.render('core_tag/index', data).done(function(html) {
55                             tagarea.replaceWith(html);
56                         });
57                     });
58             });
59         },
61         /**
62          * Initialises tag management page.
63          *
64          * @method initManagePage
65          */
66         initManagePage: function() {
68             // Set cell 'time modified' to 'now' when any of the element is updated in this row.
69             $('body').on('updated', '[data-inplaceeditable]', function(e) {
70                 str.get_string('selecttag', 'core_tag', e.ajaxreturn.value)
71                     .then(function(s) {
72                         return $('label[for="tagselect' + e.ajaxreturn.itemid + '"]').html(s);
73                     })
74                     .fail(notification.exception);
75                 str.get_string('now').done(function(s) {
76                     $(e.target).closest('tr').find('td.col-timemodified').html(s);
77                 });
78                 if (e.ajaxreturn.itemtype === 'tagflag') {
79                     var row = $(e.target).closest('tr');
80                     if (e.ajaxreturn.value === '0') {
81                         row.removeClass('flagged-tag');
82                     } else {
83                         row.addClass('flagged-tag');
84                     }
85                 }
86             });
88             // Confirmation for single tag delete link.
89             $('.tag-management-table').delegate('a.tagdelete', 'click', function(e) {
90                 e.preventDefault();
91                 var href = $(this).attr('href');
92                 str.get_strings([
93                         {key: 'delete'},
94                         {key: 'confirmdeletetag', component: 'tag'},
95                         {key: 'yes'},
96                         {key: 'no'},
97                     ]).done(function(s) {
98                         notification.confirm(s[0], s[1], s[2], s[3], function() {
99                             window.location.href = href;
100                         });
101                     }
102                 );
103             });
105             // Confirmation for bulk tag delete button.
106             $("#tag-management-delete").click(function(e) {
107                 var form = $(this).closest('form').get(0),
108                     cnt = $(form).find("input[type=checkbox]:checked").length;
109                 if (!cnt) {
110                     return;
111                 }
112                 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
113                 e.preventDefault();
114                 str.get_strings([
115                         {key: 'delete'},
116                         {key: 'confirmdeletetags', component: 'tag'},
117                         {key: 'yes'},
118                         {key: 'no'},
119                     ]).done(function(s) {
120                         notification.confirm(s[0], s[1], s[2], s[3], function() {
121                             tempElement.appendTo(form);
122                             form.submit();
123                         });
124                     }
125                 );
126             });
128             // Confirmation for bulk tag combine button.
129             $("#tag-management-combine").click(function(e) {
130                 e.preventDefault();
131                 var form = $(this).closest('form').get(0),
132                     tags = $(form).find("input[type=checkbox]:checked");
133                 if (tags.length <= 1) {
134                     str.get_strings([
135                         {key: 'combineselected', component: 'tag'},
136                         {key: 'selectmultipletags', component: 'tag'},
137                         {key: 'ok'},
138                     ]).done(function(s) {
139                             notification.alert(s[0], s[1], s[2]);
140                         }
141                     );
142                     return;
143                 }
144                 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
145                 str.get_strings([
146                     {key: 'combineselected', component: 'tag'},
147                     {key: 'selectmaintag', component: 'tag'},
148                     {key: 'continue'},
149                     {key: 'cancel'},
150                 ]).done(function(s) {
151                     var el = $('<div><form id="combinetags_form">' +
152                         '<div class="description"></div><div class="form-group options"></div>' +
153                         '<div class="form-group">' +
154                         '   <input type="submit" class="btn btn-primary" id="combinetags_submit"/>' +
155                         '   <input type="button" class="btn btn-secondary" id="combinetags_cancel"/>' +
156                         '</div>' +
157                         '</form></div>');
158                     el.find('.description').html(s[1]);
159                     el.find('#combinetags_submit').attr('value', s[2]);
160                     el.find('#combinetags_cancel').attr('value', s[3]);
161                     var fldset = el.find('.options');
162                     tags.each(function() {
163                         var tagid = $(this).val(),
164                             tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid=' + tagid + ']').attr('data-value');
165                         var option = '<div class="form-check">' +
166                             '   <input type="radio" class="form-check-input" name="maintag" ' +
167                             '       id="combinetags_maintag_' + tagid + '" value="' + tagid + '"/>' +
168                             '   <label class="form-check-label" for="combinetags_maintag_' + tagid + '">' + tagname + '</label>' +
169                             '</div>';
170                         fldset.append($(option));
171                     });
172                     // TODO: MDL-57778 Convert to core/modal.
173                     Y.use('moodle-core-notification-dialogue', function() {
174                         var panel = new M.core.dialogue({
175                             draggable: true,
176                             modal: true,
177                             closeButton: true,
178                             headerContent: s[0],
179                             bodyContent: el.html()
180                         });
181                         panel.show();
182                         $('#combinetags_form input[type=radio]').first().focus().prop('checked', true);
183                         $('#combinetags_form #combinetags_cancel').on('click', function() {
184                             panel.destroy();
185                         });
186                         $('#combinetags_form').on('submit', function() {
187                             tempElement.appendTo(form);
188                             var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();
189                             $("<input type='hidden'/>").attr('name', 'maintag').attr('value', maintag).appendTo(form);
190                             form.submit();
191                             return false;
192                         });
193                     });
194                 });
195             });
197             // When user changes tag name to some name that already exists suggest to combine the tags.
198             $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', function(e) {
199                 var exception = e.exception; // The exception object returned by the callback.
200                 var newvalue = e.newvalue; // The value that user tried to udpated the element to.
201                 var tagid = $(e.target).attr('data-itemid');
202                 if (exception.errorcode === 'namesalreadybeeingused') {
203                     e.preventDefault(); // This will prevent default error dialogue.
204                     str.get_strings([
205                         {key: 'nameuseddocombine', component: 'tag'},
206                         {key: 'yes'},
207                         {key: 'cancel'},
208                     ]).done(function(s) {
209                         notification.confirm(e.message, s[0], s[1], s[2], function() {
210                             window.location.href = window.location.href + "&newname=" + encodeURIComponent(newvalue) +
211                                 "&tagid=" + encodeURIComponent(tagid) +
212                                 '&action=renamecombine&sesskey=' + M.cfg.sesskey;
213                         });
214                     });
215                 }
216             });
218             // Form for adding standard tags.
219             $('body').on('click', 'a[data-action=addstandardtag]', function(e) {
220                 e.preventDefault();
221                 str.get_strings([
222                     {key: 'addotags', component: 'tag'},
223                     {key: 'inputstandardtags', component: 'tag'},
224                     {key: 'continue'},
225                     {key: 'cancel'},
226                 ]).done(function(s) {
227                     var el = $('<div><form id="addtags_form" method="POST">' +
228                         '<input type="hidden" name="action" value="addstandardtag"/>' +
229                         '<input type="hidden" name="sesskey" value="' + M.cfg.sesskey + '"/>' +
230                         '<div class="form-group">' +
231                         '   <label for="id_tagslist">' + s[1] + '</label>' +
232                         '   <input type="text" id="id_tagslist" class="form-control" name="tagslist"/>' +
233                         '</div>' +
234                         '<div class="form-group">' +
235                         '   <input type="submit" class="btn btn-primary" id="addtags_submit"/>' +
236                         '   <input type="button" class="btn btn-secondary" id="addtags_cancel"/>' +
237                         '</div>' +
238                         '</form></div>');
239                     el.find('#addtags_form').attr('action', window.location.href);
240                     el.find('#addtags_submit').attr('value', s[2]);
241                     el.find('#addtags_cancel').attr('value', s[3]);
242                     // TODO: MDL-57778 Convert to core/modal.
243                     Y.use('moodle-core-notification-dialogue', function() {
244                         var panel = new M.core.dialogue({
245                             draggable: true,
246                             modal: true,
247                             closeButton: true,
248                             headerContent: s[0],
249                             bodyContent: el.html()
250                         });
251                         panel.show();
252                         $('#addtags_form input[type=text]').focus();
253                         $('#addtags_form #addtags_cancel').on('click', function() {
254                             panel.destroy();
255                         });
256                     });
257                 });
258             });
259         },
261         /**
262          * Initialises tag collection management page.
263          *
264          * @method initManageCollectionsPage
265          */
266         initManageCollectionsPage: function() {
267             $('body').on('updated', '[data-inplaceeditable]', function(e) {
268                 var ajaxreturn = e.ajaxreturn,
269                     areaid, collid, isenabled;
270                 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
271                     areaid = $(this).attr('data-itemid');
272                     $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
273                     isenabled = ajaxreturn.value;
274                     if (isenabled === '1') {
275                         $(this).closest('tr').removeClass('dimmed_text');
276                         collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
277                         $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
278                     } else {
279                         $(this).closest('tr').addClass('dimmed_text');
280                     }
281                 }
282                 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {
283                     areaid = $(this).attr('data-itemid');
284                     $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
285                     collid = $(this).attr('data-value');
286                     isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
287                     if (isenabled === "1") {
288                         $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
289                     }
290                 }
291             });
293             $('body').on('click', '.addtagcoll > a', function(e) {
294                 e.preventDefault();
295                 var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
296                 str.get_strings([
297                         {key: 'addtagcoll', component: 'tag'},
298                         {key: 'name'},
299                         {key: 'searchable', component: 'tag'},
300                         {key: 'create'},
301                         {key: 'cancel'},
302                     ]).done(function(s) {
303                         var el = $('<div><form id="addtagcoll_form">' +
304                             '<div class="form-group">' +
305                             '   <label for="addtagcoll_name"></label> ' +
306                             '   <input id="addtagcoll_name" type="text" class="form-control"/>  ' +
307                             '</div>' +
308                             '<div class="form-group form-check">' +
309                             '   <input id="addtagcoll_searchable" type="checkbox" value="1" checked class="form-check-input"/>' +
310                             '   <label for="addtagcoll_searchable" class="form-check-label"></label>' +
311                             '</div>' +
312                             '<div class="form-group">' +
313                             '   <input type="submit" class="btn btn-primary" id="addtagcoll_submit"/>' +
314                             '   <input type="button" class="btn btn-secondary" id="addtagcoll_cancel"/>' +
315                             '</div>' +
316                             '</form></div>');
317                         el.find('label[for="addtagcoll_name"]').html(s[1]);
318                         el.find('label[for="addtagcoll_searchable"]').html(s[2]);
319                         el.find('#addtagcoll_submit').attr('value', s[3]);
320                         el.find('#addtagcoll_cancel').attr('value', s[4]);
321                         // TODO: MDL-57778 Convert to core/modal.
322                         Y.use('moodle-core-notification-dialogue', function() {
323                             var panel = new M.core.dialogue({
324                                 draggable: true,
325                                 modal: true,
326                                 closeButton: true,
327                                 headerContent: s[0],
328                                 bodyContent: el.html()
329                             });
330                             panel.show();
331                             $('#addtagcoll_form #addtagcoll_name').focus();
332                             $('#addtagcoll_form #addtagcoll_cancel').on('click', function() {
333                                 panel.destroy();
334                             });
335                             $('#addtagcoll_form').on('submit', function() {
336                                 var name = $('#addtagcoll_form #addtagcoll_name').val();
337                                 var searchable = $('#addtagcoll_form #addtagcoll_searchable').prop('checked') ? 1 : 0;
338                                 if (String(name).length > 0) {
339                                     window.location.href = href + "&name=" + encodeURIComponent(name) + "&searchable=" + searchable;
340                                 }
341                                 return false;
342                             });
343                         });
344                     }
345                 );
347             });
349             $('body').on('click', '.tag-collections-table .action_delete', function(e) {
350                 e.preventDefault();
351                 var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
352                 str.get_strings([
353                         {key: 'delete'},
354                         {key: 'suredeletecoll', component: 'tag', param: $(this).attr('data-collname')},
355                         {key: 'yes'},
356                         {key: 'no'},
357                     ]).done(function(s) {
358                         notification.confirm(s[0], s[1], s[2], s[3], function() {
359                             window.location.href = href;
360                         });
361                     }
362                 );
363             });
364         }
365     };
366 });