Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * Add a create new group modal to the page.
3
 *
4
 * @module     core_group/newgroup
5
 * @class      PreferencesModal
6
 * @copyright  2017 Damyon Wiese <damyon@moodle.com>
7
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8
 */
9
define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events',
10
        'core/fragment', 'core/ajax', 'block_dash/select2', 'core/notification'],
11
    function($, Str, ModalFactory, ModalEvents, Fragment, Ajax, Select2, Notification) {
12
 
13
    /**
14
     * Constructor
15
     *
16
     * @param {String} selector used to find triggers for the new group modal.
17
     * @param {int} contextid
18
     * @param {Function} onCloseCallback
19
     *
20
     * Each call to init gets it's own instance of this class.
21
     */
22
    var PreferencesModal = function(selector, contextid, onCloseCallback) {
23
        this.contextid = contextid;
24
        this.onCloseCallback = onCloseCallback;
25
        this.tab = "";
26
        this.init(selector);
27
    };
28
 
29
    /**
30
     * @var {Modal} modal
31
     * @private
32
     */
33
    PreferencesModal.prototype.modal = null;
34
 
35
    /**
36
     * @var {int} contextid
37
     * @private
38
     */
39
    PreferencesModal.prototype.contextid = -1;
40
 
41
    /**
42
     * Initialise the class.
43
     *
44
     * @param {String} selector used to find triggers for the new group modal.
45
     * @private
46
     * @return {Promise}
47
     */
48
    PreferencesModal.prototype.init = function(selector) {
49
        var triggers = $(selector);
50
        // Fetch the title string.
51
        return Str.get_string('editpreferences', 'block_dash').then(function(title) {
52
            // Create the modal.
53
            return ModalFactory.create({
54
                type: ModalFactory.types.DEFAULT,
55
                title: title,
56
                body: this.getBody()
57
            }, triggers);
58
        }.bind(this)).then(function(modal) {
59
            // Keep a reference to the modal.
60
            this.modal = modal;
61
 
62
            // Forms are big, we want a big modal.
63
            this.modal.setLarge();
64
 
65
            // We want to reset the form every time it is opened.
66
            this.modal.getRoot().on(ModalEvents.shown, function() {
67
                this.modal.setBody(this.getBody());
68
            }.bind(this));
69
 
70
            this.modal.getRoot().on('change', '#id_config_preferences_layout', this.submitFormAjax.bind(this, false));
71
 
72
            this.modal.getRoot().on('click', '[data-action=cancel]', () => {
73
                this.modal.hide();
74
            });
75
 
76
            // We catch the modal save event, and use it to submit the form inside the modal.
77
            // Triggering a form submission will give JS validation scripts a chance to check for errors.
78
            this.modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
79
            // We also catch the form submit event and use it to submit the form with ajax.
80
            this.modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this, true));
81
 
82
            this.modal.getRoot().on(ModalEvents.bodyRendered, function() {
83
                $("#fgroup_id_available_fields .form-inline > fieldset > div").sortable({
84
                    items: ".form-check-inline.fitem",
85
                    handle: ".drag-handle",
86
                    axis: "y"
87
                });
88
 
89
                this.initSelect2();
90
            }.bind(this));
91
 
92
            this.modal.getRoot().on(ModalEvents.hidden, function(e) {
93
                // Prevent "changes may be lost" popup.
94
                window.onbeforeunload = null;
95
                if (this.onCloseCallback) {
96
                    this.onCloseCallback(e);
97
                }
98
            }.bind(this));
99
 
100
            this.modal.getRoot().on('click', '[data-action=change-tab]', (e) => {
101
                this.changeTab($(e.target).data('tab'));
102
            });
103
 
104
            return this.modal;
105
        }.bind(this));
106
    };
107
 
108
    PreferencesModal.prototype.changeTab = function(tab) {
109
        this.tab = tab;
110
        this.submitFormAjax(false);
111
    };
112
 
113
    /**
114
     * Get modal body content.
115
     * @method getBody
116
     * @param {Object} formdata
117
     * @private
118
     * @return {Promise}
119
     */
120
    PreferencesModal.prototype.getBody = function(formdata) {
121
        if (typeof formdata === "undefined") {
122
            formdata = {};
123
        }
124
 
125
        // Get the content of the modal.
126
        var params = {
127
            jsonformdata: JSON.stringify(formdata),
128
            tab: this.tab
129
        };
130
        return Fragment.loadFragment('block_dash', 'block_preferences_form', this.contextid, params);
131
    };
132
 
133
    /**
134
     * Form submission handler.
135
     * @method handleFormSubmissionResponse
136
     * @param {Object} formData
137
     * @param {Boolean} closeWhenDone
138
     * @param {Object} response
139
     * @private
140
     */
141
    PreferencesModal.prototype.handleFormSubmissionResponse = function(formData, closeWhenDone, response) {
142
        if (response.validationerrors || !closeWhenDone) {
143
            this.modal.setBody(this.getBody(formData));
144
        } else if (closeWhenDone) {
145
            this.modal.hide();
146
        }
147
    };
148
 
149
    /**
150
     * @method handleFormSubmissionFailure
151
     * @param {Object} data
152
     * @private
153
     */
154
    PreferencesModal.prototype.handleFormSubmissionFailure = function(data) {
155
        // Oh noes! Epic fail :(
156
        // Ah wait - this is normal. We need to re-display the form with errors!
157
        this.modal.setBody(this.getBody(data));
158
    };
159
 
160
    /**
161
     * Private method
162
     *
163
     * @method submitFormAjax
164
     * @private
165
     * @param {boolean} closeWhenDone If true modal will close after successful submission.
166
     * @param {Event} e Form submission event.
167
     */
168
    PreferencesModal.prototype.submitFormAjax = function(closeWhenDone, e) {
169
        // We don't want to do a real form submission.
170
        if (e) {
171
            e.preventDefault();
172
        }
173
 
174
        // Now the change events have run, see if there are any "invalid" form fields.
175
        var invalid = $.merge(
176
            this.modal.getRoot().find('[aria-invalid="true"]'),
177
            this.modal.getRoot().find('.error')
178
        );
179
 
180
        // If we found invalid fields, focus on the first one and do not submit via ajax.
181
        if (invalid.length) {
182
            invalid.first().focus();
183
            return;
184
        }
185
 
186
        // Convert all the form elements values to a serialised string.
187
        var formData = this.modal.getRoot().find('form').serialize();
188
 
189
        // Now we can continue...
190
        Ajax.call([{
191
            methodname: 'block_dash_submit_preferences_form',
192
            args: {
193
                contextid: this.contextid,
194
                jsonformdata: JSON.stringify(formData)
195
            },
196
            done: this.handleFormSubmissionResponse.bind(this, formData, closeWhenDone),
197
            fail: this.handleFormSubmissionFailure.bind(this, formData)
198
        }])[0].fail(Notification.exception);
199
    };
200
 
201
    PreferencesModal.prototype.getModal = function() {
202
        return this.modal;
203
    };
204
 
205
    /**
206
     * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
207
     *
208
     * @method submitForm
209
     * @param {Event} e Form submission event.
210
     * @private
211
     */
212
    PreferencesModal.prototype.submitForm = function(e) {
213
        e.preventDefault();
214
        this.modal.getRoot().find('form').submit();
215
    };
216
 
217
    PreferencesModal.prototype.initSelect2 = function() {
218
        this.modal.getRoot().find('.select2-form select').each(function(index, element) {
219
            let placeholder = null;
220
            if ($(element).find("option[value='-1']")) {
221
                placeholder = {
222
                    id: '-1', // The value of the option
223
                    text: $(element).find("option[value='-1']").text()
224
                };
225
            }
226
            $(element).select2({
227
                dropdownParent: $(this).parent(),
228
                allowClear: true,
229
                theme: 'bootstrap4',
230
                placeholder: placeholder
231
            }).on('select2:unselecting', function() {
232
                $(this).data('unselecting', true);
233
            }).on('select2:opening', function(e) {
234
                if ($(this).data('unselecting')) {
235
                    $(this).removeData('unselecting');
236
                    e.preventDefault();
237
                }
238
            });
239
        });
240
    };
241
 
242
    return PreferencesModal;
243
});