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
 * A javascript module to handle calendar drag and drop in the calendar
18
 * month view navigation.
19
 *
20
 * This code is run each time the calendar month view is re-rendered. We
21
 * only register the event handlers once per page load so that the in place
22
 * DOM updates that happen on month change don't continue to register handlers.
23
 *
24
 * @module     core_calendar/month_navigation_drag_drop
25
 * @copyright  2017 Ryan Wyllie <ryan@moodle.com>
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 */
28
define([
29
            'jquery',
30
            'core_calendar/drag_drop_data_store',
31
        ],
32
        function(
33
            $,
34
            DataStore
35
        ) {
36
 
37
    var SELECTORS = {
38
        DRAGGABLE: '[draggable="true"][data-region="event-item"]',
39
        DROP_ZONE: '[data-drop-zone="nav-link"]',
40
    };
41
    var HOVER_CLASS = 'bg-primary text-white';
42
    var TARGET_CLASS = 'drop-target';
43
    var HOVER_TIME = 1000; // 1 second hover to change month.
44
 
45
    // We store some static variables at the module level because this
46
    // module is called each time the calendar month view is reloaded but
47
    // we want some actions to only occur ones.
48
 
49
    /* @var {bool} registered If the event listeners have been added */
50
    var registered = false;
51
    /* @var {int} hoverTimer The timeout id of any timeout waiting for hover */
52
    var hoverTimer = null;
53
    /* @var {object} root The root nav element we're operating on */
54
    var root = null;
55
 
56
    /**
57
     * Add or remove the appropriate styling to indicate whether
58
     * the drop target is being hovered over.
59
     *
60
     * @param {object} target The target drop zone element
61
     * @param {bool} hovered If the element is hovered over ot not
62
     */
63
    var updateHoverState = function(target, hovered) {
64
        if (hovered) {
65
            target.addClass(HOVER_CLASS);
66
        } else {
67
            target.removeClass(HOVER_CLASS);
68
        }
69
    };
70
 
71
    /**
72
     * Add some styling to the UI to indicate that the nav links
73
     * are an acceptable drop target.
74
     */
75
    var addDropZoneIndicator = function() {
76
        root.find(SELECTORS.DROP_ZONE).addClass(TARGET_CLASS);
77
    };
78
 
79
    /**
80
     * Remove the styling from the nav links.
81
     */
82
    var removeDropZoneIndicator = function() {
83
        root.find(SELECTORS.DROP_ZONE).removeClass(TARGET_CLASS);
84
    };
85
 
86
    /**
87
     * Get the drop zone target from the event, if one is found.
88
     *
89
     * @param {event} e Javascript event
90
     * @return {object|null}
91
     */
92
    var getTargetFromEvent = function(e) {
93
        var target = $(e.target).closest(SELECTORS.DROP_ZONE);
94
        return (target.length) ? target : null;
95
    };
96
 
97
    /**
98
     * This will add a visual indicator to the calendar UI to
99
     * indicate which nav link is a valid drop zone.
100
     *
101
     * @param {Event} e
102
     */
103
    var dragstartHandler = function(e) {
104
        // Make sure the drag event is for a calendar event.
105
        var eventElement = $(e.target).closest(SELECTORS.DRAGGABLE);
106
 
107
        if (eventElement.length) {
108
            addDropZoneIndicator();
109
        }
110
    };
111
 
112
    /**
113
     * Update the hover state of the target nav element when
114
     * the user is dragging an event over it.
115
     *
116
     * This will add a visual indicator to the calendar UI to
117
     * indicate which nav link is being hovered.
118
     *
119
     * @param {event} e The dragover event
120
     */
121
    var dragoverHandler = function(e) {
122
        // Ignore dragging of non calendar events.
123
        if (!DataStore.hasEventId()) {
124
            return;
125
        }
126
 
127
        e.preventDefault();
128
        var target = getTargetFromEvent(e);
129
 
130
        if (!target) {
131
            return;
132
        }
133
 
134
        // If we're not draggin a calendar event then
135
        // ignore it.
136
        if (!DataStore.hasEventId()) {
137
            return;
138
        }
139
 
140
        if (!hoverTimer) {
141
            hoverTimer = setTimeout(function() {
142
                target.click();
143
                hoverTimer = null;
144
            }, HOVER_TIME);
145
        }
146
 
147
        updateHoverState(target, true);
148
        removeDropZoneIndicator();
149
    };
150
 
151
    /**
152
     * Update the hover state of the target nav element that was
153
     * previously dragged over but has is no longer a drag target.
154
     *
155
     * This will remove the visual indicator from the calendar UI
156
     * that was added by the dragoverHandler.
157
     *
158
     * @param {event} e The dragstart event
159
     */
160
    var dragleaveHandler = function(e) {
161
        // Ignore dragging of non calendar events.
162
        if (!DataStore.hasEventId()) {
163
            return;
164
        }
165
 
166
        var target = getTargetFromEvent(e);
167
 
168
        if (!target) {
169
            return;
170
        }
171
 
172
        if (hoverTimer) {
173
            clearTimeout(hoverTimer);
174
            hoverTimer = null;
175
        }
176
 
177
        updateHoverState(target, false);
178
        addDropZoneIndicator();
179
        e.preventDefault();
180
    };
181
 
182
    /**
183
     * Remove the visual indicator from the calendar UI that was
184
     * added by the dragoverHandler.
185
     *
186
     * @param {event} e The drop event
187
     */
188
    var dropHandler = function(e) {
189
        // Ignore dragging of non calendar events.
190
        if (!DataStore.hasEventId()) {
191
            return;
192
        }
193
 
194
        removeDropZoneIndicator();
195
        var target = getTargetFromEvent(e);
196
 
197
        if (!target) {
198
            return;
199
        }
200
 
201
        updateHoverState(target, false);
202
        e.preventDefault();
203
    };
204
 
205
    return {
206
        /**
207
         * Initialise the event handlers for the drag events.
208
         *
209
         * @param {object} rootElement The element containing calendar nav links
210
         */
211
        init: function(rootElement) {
212
            // Only register the handlers once on the first load.
213
            if (!registered) {
214
                // These handlers are only added the first time the module
215
                // is loaded because we don't want to have a new listener
216
                // added each time the "init" function is called otherwise we'll
217
                // end up with lots of stale handlers.
218
                document.addEventListener('dragstart', dragstartHandler, false);
219
                document.addEventListener('dragover', dragoverHandler, false);
220
                document.addEventListener('dragleave', dragleaveHandler, false);
221
                document.addEventListener('drop', dropHandler, false);
222
                document.addEventListener('dragend', removeDropZoneIndicator, false);
223
                registered = true;
224
            }
225
 
226
            // Update the module variable to operate on the given
227
            // root element.
228
            root = $(rootElement);
229
 
230
            // If we're currently dragging then add the indicators.
231
            if (DataStore.hasEventId()) {
232
                addDropZoneIndicator();
233
            }
234
        },
235
    };
236
});