Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
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
 * Submit button JavaScript. All submit buttons will be automatically disabled once the form is
18
 * submitted, unless that submission results in an error/cancelling the submit.
19
 *
20
 * @module core_form/submit
21
 * @copyright 2019 The Open University
22
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @since 3.8
24
 */
25
 
26
import {eventTypes} from 'core_form/events';
27
 
28
/** @property {number} ID for setInterval used when polling for download cookie */
29
let cookieListener = 0;
30
 
31
/** @property {Array} Array of buttons that need re-enabling if we get a download cookie */
32
const cookieListeningButtons = [];
33
 
34
/** @property {number} Number of files uploading. */
35
let currentUploadCount = 0;
36
 
37
/** @property {Array} Array of buttons that need re-enabling if we get a upload process. */
38
const uploadListeningButtons = [];
39
 
40
/** @property {Boolean} Is upload listeners registered? */
41
let uploadListenersRegistered = false;
42
 
43
/**
44
 * Listens in case a download cookie is provided.
45
 *
46
 * This function is used to detect file downloads. If there is a file download then we get a
47
 * beforeunload event, but the page is never unloaded and when the file download completes we
48
 * should re-enable the buttons. We detect this by watching for a specific cookie.
49
 *
50
 * PHP function \core_form\util::form_download_complete() can be used to send this cookie.
51
 *
52
 * @param {HTMLElement} button Button to re-enable
53
 */
54
const listenForDownloadCookie = (button) => {
55
    cookieListeningButtons.push(button);
56
    if (!cookieListener) {
57
        cookieListener = setInterval(() => {
58
            // Look for cookie.
59
            const parts = document.cookie.split(getCookieName() + '=');
60
            if (parts.length == 2) {
61
                // We found the cookie, so the file is ready. Expire the cookie and cancel polling.
62
                clearDownloadCookie();
63
                clearInterval(cookieListener);
64
                cookieListener = 0;
65
 
66
                // Re-enable all the buttons.
67
                cookieListeningButtons.forEach((button) => {
68
                    button.disabled = false;
69
                });
70
            }
71
        }, 500);
72
    }
73
};
74
 
75
/**
76
 * Gets a unique name for the download cookie.
77
 *
78
 * @returns {string} Cookie name
79
 */
80
const getCookieName = () => {
81
    return 'moodledownload_' + M.cfg.sesskey;
82
};
83
 
84
/**
85
 * Clears the download cookie if there is one.
86
 */
87
const clearDownloadCookie = () => {
88
    document.cookie = encodeURIComponent(getCookieName()) + '=deleted; expires=' + new Date(0).toUTCString();
89
};
90
 
91
/**
92
 * Enable submit buttons when all files are uploaded.
93
 */
94
const checkUploadCount = () => {
95
    if (currentUploadCount) {
96
        uploadListeningButtons.forEach(button => {
97
            button.disabled = true;
98
        });
99
    } else {
100
        uploadListeningButtons.forEach(button => {
101
            button.disabled = false;
102
        });
103
    }
104
};
105
 
106
/**
107
 * Initialises submit buttons.
108
 *
109
 * @param {String} elementId Form button element
110
 * @listens event:uploadStarted
111
 * @listens event:uploadCompleted
112
 */
113
export const init = (elementId) => {
114
    const button = document.getElementById(elementId);
115
    if (button === null) {
116
        // Exit early if invalid element id passed.
117
        return;
118
    }
119
 
120
    // If buttons are disabled by default, we do not enable them when file upload completed event is fired.
121
    if (!button.disabled) {
122
        uploadListeningButtons.push(button);
123
    }
124
 
125
    if (!uploadListenersRegistered) {
126
        // Add event listener for file upload start.
127
        document.addEventListener(eventTypes.uploadStarted, () => {
128
            currentUploadCount++;
129
            checkUploadCount();
130
        });
131
 
132
        // Add event listener for file upload complete.
133
        document.addEventListener(eventTypes.uploadCompleted, () => {
134
            currentUploadCount--;
135
            checkUploadCount();
136
        });
137
        uploadListenersRegistered = true;
138
    }
139
 
140
    // If the form has double submit protection disabled, do nothing.
141
    if (button.form.dataset.doubleSubmitProtection === 'off') {
142
        return;
143
    }
144
    button.form.addEventListener('submit', function(event) {
145
        // Only disable it if the browser is really going to another page as a result of the
146
        // submit.
147
        const disableAction = function() {
148
            // If the submit was cancelled, or the button is already disabled, don't do anything.
149
            if (event.defaultPrevented || button.disabled) {
150
                return;
151
            }
152
 
153
            button.disabled = true;
154
            clearDownloadCookie();
155
            listenForDownloadCookie(button);
156
        };
157
        window.addEventListener('beforeunload', disableAction);
158
        // If there is no beforeunload event as a result of this form submit, then the form
159
        // submit must have been cancelled, so don't disable the button if the page is
160
        // unloaded later.
161
        setTimeout(function() {
162
            window.removeEventListener('beforeunload', disableAction);
163
        }, 1);
164
    }, false);
165
};