MDL-62746 tag: Convert YUI modals to AMD modals
[moodle.git] / lib / amd / src / tag.js
CommitLineData
8e355853
MG
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 * 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 */
65cac800
JP
25define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/modal_factory', 'core/modal_events'],
26 function($, ajax, templates, notification, str, ModalFactory, ModalEvents) {
8e355853
MG
27 return /** @alias module:core/tag */ {
28
29 /**
c026a28d 30 * Initialises tag index page.
8e355853 31 *
131b78b9 32 * @method initTagindexPage
c026a28d 33 */
131b78b9 34 initTagindexPage: function() {
c026a28d
MG
35 // Click handler for changing tag type.
36 $('body').delegate('.tagarea[data-ta] a[data-quickload=1]', 'click', function(e) {
37 e.preventDefault();
35be5826 38 var target = $(this),
eb3839df 39 query = target[0].search.replace(/^\?/, ''),
c026a28d 40 tagarea = target.closest('.tagarea[data-ta]'),
c96f55e6
DP
41 args = query.split('&').reduce(function(s, c) {
42 var t = c.split('=');
43 s[t[0]] = decodeURIComponent(t[1]);
44 return s;
45 }, {});
c026a28d
MG
46
47 var promises = ajax.call([{
48 methodname: 'core_tag_get_tagindex',
9f5f3dcc 49 args: {tagindex: args}
c026a28d
MG
50 }], true);
51
52 $.when.apply($, promises)
35be5826 53 .done(function(data) {
c026a28d
MG
54 templates.render('core_tag/index', data).done(function(html) {
55 tagarea.replaceWith(html);
56 });
57 });
58 });
59 },
60
61 /**
62 * Initialises tag management page.
63 *
131b78b9 64 * @method initManagePage
8e355853 65 */
131b78b9 66 initManagePage: function() {
8e355853 67
21d9596c
MG
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) {
39e14b23
AN
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);
21d9596c
MG
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 }
8e355853 85 }
8e355853
MG
86 });
87
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([
35be5826
DP
93 {key: 'delete'},
94 {key: 'confirmdeletetag', component: 'tag'},
95 {key: 'yes'},
96 {key: 'no'},
8e355853
MG
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 });
104
105 // Confirmation for bulk tag delete button.
35be5826 106 $("#tag-management-delete").click(function(e) {
8e355853
MG
107 var form = $(this).closest('form').get(0),
108 cnt = $(form).find("input[type=checkbox]:checked").length;
109 if (!cnt) {
5602dc17 110 return;
8e355853 111 }
0d202789 112 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
8e355853
MG
113 e.preventDefault();
114 str.get_strings([
35be5826
DP
115 {key: 'delete'},
116 {key: 'confirmdeletetags', component: 'tag'},
117 {key: 'yes'},
118 {key: 'no'},
8e355853
MG
119 ]).done(function(s) {
120 notification.confirm(s[0], s[1], s[2], s[3], function() {
0d202789 121 tempElement.appendTo(form);
8e355853
MG
122 form.submit();
123 });
124 }
125 );
126 });
0d202789
MG
127
128 // Confirmation for bulk tag combine button.
35be5826 129 $("#tag-management-combine").click(function(e) {
0d202789
MG
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([
35be5826
DP
135 {key: 'combineselected', component: 'tag'},
136 {key: 'selectmultipletags', component: 'tag'},
137 {key: 'ok'},
0d202789
MG
138 ]).done(function(s) {
139 notification.alert(s[0], s[1], s[2]);
140 }
141 );
5602dc17 142 return;
0d202789
MG
143 }
144 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
65cac800
JP
145 var saveButtonText = '';
146 var tagOptions = [];
147 tags.each(function() {
148 var tagid = $(this).val(),
149 tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid=' + tagid + ']').attr('data-value');
150 tagOptions.push({
151 id: tagid,
152 name: tagname
153 });
154 });
155
0d202789 156 str.get_strings([
35be5826 157 {key: 'combineselected', component: 'tag'},
65cac800
JP
158 {key: 'continue'}
159 ]).then(function(langStrings) {
160 var modalTitle = langStrings[0];
161 saveButtonText = langStrings[1];
162 var templateContext = {
163 tags: tagOptions
164 };
165 return ModalFactory.create({
166 title: modalTitle,
167 body: templates.render('core_tag/combine_tags', templateContext),
168 type: ModalFactory.types.SAVE_CANCEL
0d202789 169 });
65cac800
JP
170 }).then(function(modal) {
171 modal.setSaveButtonText(saveButtonText);
172
173 // Handle save event.
174 modal.getRoot().on(ModalEvents.save, function(e) {
175 e.preventDefault();
176
177 // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?
178 tempElement.appendTo(form);
179 // Get the selected tag from the modal.
180 var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();
181 // Append this in the tags list form.
182 $("<input type='hidden'/>").attr('name', 'maintag').attr('value', maintag).appendTo(form);
183 // Submit the tags list form.
184 form.submit();
0d202789 185 });
65cac800
JP
186
187 // Handle hidden event.
188 modal.getRoot().on(ModalEvents.hidden, function() {
189 // Destroy when hidden.
190 modal.destroy();
191 });
192
193 modal.show();
194 // Tick the first option.
195 $('#combinetags_form input[type=radio]').first().focus().prop('checked', true);
196
197 return;
198
199 }).catch(notification.exception);
0d202789
MG
200 });
201
202 // When user changes tag name to some name that already exists suggest to combine the tags.
203 $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', function(e) {
204 var exception = e.exception; // The exception object returned by the callback.
205 var newvalue = e.newvalue; // The value that user tried to udpated the element to.
206 var tagid = $(e.target).attr('data-itemid');
207 if (exception.errorcode === 'namesalreadybeeingused') {
208 e.preventDefault(); // This will prevent default error dialogue.
209 str.get_strings([
35be5826
DP
210 {key: 'nameuseddocombine', component: 'tag'},
211 {key: 'yes'},
212 {key: 'cancel'},
0d202789
MG
213 ]).done(function(s) {
214 notification.confirm(e.message, s[0], s[1], s[2], function() {
215 window.location.href = window.location.href + "&newname=" + encodeURIComponent(newvalue) +
216 "&tagid=" + encodeURIComponent(tagid) +
217 '&action=renamecombine&sesskey=' + M.cfg.sesskey;
218 });
219 });
220 }
221 });
1e34257e
MG
222
223 // Form for adding standard tags.
224 $('body').on('click', 'a[data-action=addstandardtag]', function(e) {
225 e.preventDefault();
65cac800
JP
226
227 var saveButtonText = '';
1e34257e 228 str.get_strings([
35be5826 229 {key: 'addotags', component: 'tag'},
65cac800
JP
230 {key: 'continue'}
231 ]).then(function(langStrings) {
232 var modalTitle = langStrings[0];
233 saveButtonText = langStrings[1];
234 var templateContext = {
235 actionurl: window.location.href,
236 sesskey: M.cfg.sesskey
237 };
238 return ModalFactory.create({
239 title: modalTitle,
240 body: templates.render('core_tag/add_tags', templateContext),
241 type: ModalFactory.types.SAVE_CANCEL
242 });
243 }).then(function(modal) {
244 modal.setSaveButtonText(saveButtonText);
245
246 // Handle save event.
247 modal.getRoot().on(ModalEvents.save, function(e) {
248 var tagsInput = $(e.currentTarget).find('#id_tagslist');
249 var name = tagsInput.val().trim();
250
251 // Set the text field's value to the trimmed value.
252 tagsInput.val(name);
253
254 // Add submit event listener to the form.
255 var tagsForm = $('#addtags_form');
256 tagsForm.on('submit', function(e) {
257 // Validate the form.
258 var form = $('#addtags_form');
259 if (form[0].checkValidity() === false) {
260 e.preventDefault();
261 e.stopPropagation();
262 }
263 form.addClass('was-validated');
264
265 // BS2 compatibility.
266 $('[data-region="tagslistinput"]').addClass('error');
267 var errorMessage = $('#id_tagslist_error_message');
268 errorMessage.removeAttr('hidden');
269 errorMessage.addClass('help-block');
e7ecb4a9 270 });
65cac800
JP
271
272 // Try to submit the form.
273 tagsForm.submit();
274
275 return false;
1e34257e 276 });
65cac800
JP
277
278 // Handle hidden event.
279 modal.getRoot().on(ModalEvents.hidden, function() {
280 // Destroy when hidden.
281 modal.destroy();
282 });
283
284 modal.show();
285
286 return;
287
288 }).catch(notification.exception);
1e34257e 289 });
131b78b9
MG
290 },
291
292 /**
293 * Initialises tag collection management page.
294 *
295 * @method initManageCollectionsPage
296 */
297 initManageCollectionsPage: function() {
298 $('body').on('updated', '[data-inplaceeditable]', function(e) {
352bfbf5 299 var ajaxreturn = e.ajaxreturn,
352bfbf5 300 areaid, collid, isenabled;
131b78b9 301 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
352bfbf5 302 areaid = $(this).attr('data-itemid');
63e4df60 303 $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
352bfbf5 304 isenabled = ajaxreturn.value;
131b78b9
MG
305 if (isenabled === '1') {
306 $(this).closest('tr').removeClass('dimmed_text');
352bfbf5 307 collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
63e4df60 308 $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
131b78b9
MG
309 } else {
310 $(this).closest('tr').addClass('dimmed_text');
311 }
312 }
313 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {
352bfbf5 314 areaid = $(this).attr('data-itemid');
63e4df60 315 $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
352bfbf5
MG
316 collid = $(this).attr('data-value');
317 isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
131b78b9 318 if (isenabled === "1") {
63e4df60 319 $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
131b78b9
MG
320 }
321 }
352bfbf5
MG
322 });
323
324 $('body').on('click', '.addtagcoll > a', function(e) {
325 e.preventDefault();
65cac800
JP
326 var keys = [
327 {
328 key: 'addtagcoll',
329 component: 'tag'
330 },
331 {
332 key: 'create'
352bfbf5 333 }
65cac800
JP
334 ];
335
336 var href = $(this).attr('data-url');
337 var saveButtonText = '';
338 str.get_strings(keys).then(function(langStrings) {
339 var modalTitle = langStrings[0];
340 saveButtonText = langStrings[1];
341 var templateContext = {
342 actionurl: href,
343 sesskey: M.cfg.sesskey
344 };
345 return ModalFactory.create({
346 title: modalTitle,
347 body: templates.render('core_tag/add_tag_collection', templateContext),
348 type: ModalFactory.types.SAVE_CANCEL
349 });
350 }).then(function(modal) {
351 modal.setSaveButtonText(saveButtonText);
352
353 // Handle save event.
354 modal.getRoot().on(ModalEvents.save, function(e) {
355 var collectionInput = $(e.currentTarget).find('#addtagcoll_name');
356 var name = collectionInput.val().trim();
357 // Set the text field's value to the trimmed value.
358 collectionInput.val(name);
359
360 // Add submit event listener to the form.
361 var form = $('#addtagcoll_form');
362 form.on('submit', function(e) {
363 // Validate the form.
364 if (form[0].checkValidity() === false) {
365 e.preventDefault();
366 e.stopPropagation();
367 }
368 form.addClass('was-validated');
369
370 // BS2 compatibility.
371 $('[data-region="addtagcoll_nameinput"]').addClass('error');
372 var errorMessage = $('#id_addtagcoll_name_error_message');
373 errorMessage.removeAttr('hidden');
374 errorMessage.addClass('help-block');
375 });
376
377 // Try to submit the form.
378 form.submit();
379
380 return false;
381 });
382
383 // Handle hidden event.
384 modal.getRoot().on(ModalEvents.hidden, function() {
385 // Destroy when hidden.
386 modal.destroy();
387 });
388
389 modal.show();
390
391 return;
352bfbf5 392
65cac800 393 }).catch(notification.exception);
352bfbf5
MG
394 });
395
396 $('body').on('click', '.tag-collections-table .action_delete', function(e) {
397 e.preventDefault();
398 var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
399 str.get_strings([
35be5826 400 {key: 'delete'},
9f5f3dcc 401 {key: 'suredeletecoll', component: 'tag', param: $(this).attr('data-collname')},
35be5826
DP
402 {key: 'yes'},
403 {key: 'no'},
352bfbf5
MG
404 ]).done(function(s) {
405 notification.confirm(s[0], s[1], s[2], s[3], function() {
406 window.location.href = href;
407 });
408 }
409 );
410 });
8e355853
MG
411 }
412 };
c96f55e6 413});