Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"month_view_drag_drop.min.js","sources":["../src/month_view_drag_drop.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to handle calendar drag and drop in the calendar\n * month view.\n *\n * @module     core_calendar/month_view_drag_drop\n * @copyright  2017 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n            'jquery',\n            'core/notification',\n            'core/str',\n            'core_calendar/events',\n            'core_calendar/drag_drop_data_store'\n        ],\n        function(\n            $,\n            Notification,\n            Str,\n            CalendarEvents,\n            DataStore\n        ) {\n\n    var SELECTORS = {\n        ROOT: \"[data-region='calendar']\",\n        DRAGGABLE: '[draggable=\"true\"][data-region=\"event-item\"]',\n        DROP_ZONE: '[data-drop-zone=\"month-view-day\"]',\n        WEEK: '[data-region=\"month-view-week\"]',\n    };\n    var INVALID_DROP_ZONE_CLASS = 'bg-faded';\n    var INVALID_HOVER_CLASS = 'bg-danger text-white';\n    var VALID_HOVER_CLASS = 'bg-primary text-white';\n    var ALL_CLASSES = INVALID_DROP_ZONE_CLASS + ' ' + INVALID_HOVER_CLASS + ' ' + VALID_HOVER_CLASS;\n    /* @var {bool} registered If the event listeners have been added */\n    var registered = false;\n\n    /**\n     * Get the correct drop zone element from the given javascript\n     * event.\n     *\n     * @param {event} e The javascript event\n     * @return {object|null}\n     */\n    var getDropZoneFromEvent = function(e) {\n        var dropZone = $(e.target).closest(SELECTORS.DROP_ZONE);\n        return (dropZone.length) ? dropZone : null;\n    };\n\n    /**\n     * Determine if the given dropzone element is within the acceptable\n     * time range.\n     *\n     * The drop zone timestamp is midnight on that day so we should check\n     * that the event's acceptable timestart value\n     *\n     * @param {object} dropZone The drop zone day from the calendar\n     * @return {bool}\n     */\n    var isValidDropZone = function(dropZone) {\n        var dropTimestamp = dropZone.attr('data-day-timestamp');\n        var minTimestart = DataStore.getMinTimestart();\n        var maxTimestart = DataStore.getMaxTimestart();\n\n        if (minTimestart && minTimestart > dropTimestamp) {\n            return false;\n        }\n\n        if (maxTimestart && maxTimestart < dropTimestamp) {\n            return false;\n        }\n\n        return true;\n    };\n\n    /**\n     * Get the error string to display for a given drop zone element\n     * if it is invalid.\n     *\n     * @param {object} dropZone The drop zone day from the calendar\n     * @return {string}\n     */\n    var getDropZoneError = function(dropZone) {\n        var dropTimestamp = dropZone.attr('data-day-timestamp');\n        var minTimestart = DataStore.getMinTimestart();\n        var maxTimestart = DataStore.getMaxTimestart();\n\n        if (minTimestart && minTimestart > dropTimestamp) {\n            return DataStore.getMinError();\n        }\n\n        if (maxTimestart && maxTimestart < dropTimestamp) {\n            return DataStore.getMaxError();\n        }\n\n        return null;\n    };\n\n    /**\n     * Remove all of the styling from each of the drop zones in the calendar.\n     */\n    var clearAllDropZonesState = function() {\n        $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n            dropZone = $(dropZone);\n            dropZone.removeClass(ALL_CLASSES);\n        });\n    };\n\n    /**\n     * Update the hover state for the event in the calendar to reflect\n     * which days the event will be moved to.\n     *\n     * If the drop zone is not being hovered then it will apply some\n     * styling to reflect whether the drop zone is a valid or invalid\n     * drop place for the current dragging event.\n     *\n     * This funciton supports events spanning multiple days and will\n     * recurse to highlight (or remove highlight) each of the days\n     * that the event will be moved to.\n     *\n     * For example: An event with a duration of 3 days will have\n     * 3 days highlighted when it's dragged elsewhere in the calendar.\n     * The current drag target and the 2 days following it (including\n     * wrapping to the next week if necessary).\n     *\n     * @param {string|object} dropZone The drag target element\n     * @param {bool} hovered If the target is hovered or not\n     * @param {Number} count How many days to highlight (default to duration)\n     */\n    var updateHoverState = function(dropZone, hovered, count) {\n        if (typeof count === 'undefined') {\n            // This is how many days we need to highlight.\n            count = DataStore.getDurationDays();\n        }\n\n        var valid = isValidDropZone(dropZone);\n        dropZone.removeClass(ALL_CLASSES);\n\n        if (hovered) {\n\n            if (valid) {\n                dropZone.addClass(VALID_HOVER_CLASS);\n            } else {\n                dropZone.addClass(INVALID_HOVER_CLASS);\n            }\n        } else {\n            dropZone.removeClass(VALID_HOVER_CLASS + ' ' + INVALID_HOVER_CLASS);\n\n            if (!valid) {\n                dropZone.addClass(INVALID_DROP_ZONE_CLASS);\n            }\n        }\n\n        count--;\n\n        // If we've still got days to highlight then we should\n        // find the next day.\n        if (count > 0) {\n            var nextDropZone = dropZone.next();\n\n            // If there are no more days in this week then we\n            // need to move down to the next week in the calendar.\n            if (!nextDropZone.length) {\n                var nextWeek = dropZone.closest(SELECTORS.WEEK).next();\n\n                if (nextWeek.length) {\n                    nextDropZone = nextWeek.children(SELECTORS.DROP_ZONE).first();\n                }\n            }\n\n            // If we found another day then let's recursively\n            // update it's hover state.\n            if (nextDropZone.length) {\n                updateHoverState(nextDropZone, hovered, count);\n            }\n        }\n    };\n\n    /**\n     * Find all of the calendar event drop zones in the calendar and update the display\n     * for the user to indicate which zones are valid and invalid.\n     */\n    var updateAllDropZonesState = function() {\n        $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n            dropZone = $(dropZone);\n\n            if (!isValidDropZone(dropZone)) {\n                updateHoverState(dropZone, false);\n            }\n        });\n    };\n\n\n    /**\n     * Set up the module level variables to track which event is being\n     * dragged and how many days it spans.\n     *\n     * @param {event} e The dragstart event\n     */\n    var dragstartHandler = function(e) {\n        var target = $(e.target);\n        var draggableElement = target.closest(SELECTORS.DRAGGABLE);\n\n        if (!draggableElement.length) {\n            return;\n        }\n\n        var eventElement = draggableElement.find('[data-event-id]');\n        var eventId = eventElement.attr('data-event-id');\n        var minTimestart = draggableElement.attr('data-min-day-timestamp');\n        var maxTimestart = draggableElement.attr('data-max-day-timestamp');\n        var minError = draggableElement.attr('data-min-day-error');\n        var maxError = draggableElement.attr('data-max-day-error');\n        var eventsSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n        var duration = $(eventsSelector).length;\n\n        DataStore.setEventId(eventId);\n        DataStore.setDurationDays(duration);\n\n        if (minTimestart) {\n            DataStore.setMinTimestart(minTimestart);\n        }\n\n        if (maxTimestart) {\n            DataStore.setMaxTimestart(maxTimestart);\n        }\n\n        if (minError) {\n            DataStore.setMinError(minError);\n        }\n\n        if (maxError) {\n            DataStore.setMaxError(maxError);\n        }\n\n        e.dataTransfer.effectAllowed = \"move\";\n        e.dataTransfer.dropEffect = \"move\";\n        // Firefox requires a value to be set here or the drag won't\n        // work and the dragover handler won't fire.\n        e.dataTransfer.setData('text/plain', eventId);\n        e.dropEffect = \"move\";\n\n        updateAllDropZonesState();\n    };\n\n    /**\n     * Update the hover state of the target day element when\n     * the user is dragging an event over it.\n     *\n     * This will add a visual indicator to the calendar UI to\n     * indicate which day(s) the event will be moved to.\n     *\n     * @param {event} e The dragstart event\n     */\n    var dragoverHandler = function(e) {\n        // Ignore dragging of non calendar events.\n        if (!DataStore.hasEventId()) {\n            return;\n        }\n\n        e.preventDefault();\n\n        var dropZone = getDropZoneFromEvent(e);\n\n        if (!dropZone) {\n            return;\n        }\n\n        updateHoverState(dropZone, true);\n    };\n\n    /**\n     * Update the hover state of the target day element that was\n     * previously dragged over but has is no longer a drag target.\n     *\n     * This will remove the visual indicator from the calendar UI\n     * that was added by the dragoverHandler.\n     *\n     * @param {event} e The dragstart event\n     */\n    var dragleaveHandler = function(e) {\n        // Ignore dragging of non calendar events.\n        if (!DataStore.hasEventId()) {\n            return;\n        }\n\n        var dropZone = getDropZoneFromEvent(e);\n\n        if (!dropZone) {\n            return;\n        }\n\n        updateHoverState(dropZone, false);\n        e.preventDefault();\n    };\n\n    /**\n     * Determines the event element, origin day, and destination day\n     * once the user drops the calendar event. These three bits of data\n     * are provided as the payload to the \"moveEvent\" calendar javascript\n     * event that is fired.\n     *\n     * This will remove the visual indicator from the calendar UI\n     * that was added by the dragoverHandler.\n     *\n     * @param {event} e The dragstart event\n     */\n    var dropHandler = function(e) {\n        // Ignore dragging of non calendar events.\n        if (!DataStore.hasEventId()) {\n            return;\n        }\n\n        var dropZone = getDropZoneFromEvent(e);\n\n        if (!dropZone) {\n            DataStore.clearAll();\n            clearAllDropZonesState();\n            return;\n        }\n\n        if (isValidDropZone(dropZone)) {\n            var eventId = DataStore.getEventId();\n            var eventElementSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n            var eventElement = $(eventElementSelector);\n            var origin = null;\n\n            if (eventElement.length) {\n                origin = eventElement.closest(SELECTORS.DROP_ZONE);\n            }\n\n            $('body').trigger(CalendarEvents.moveEvent, [eventId, origin, dropZone]);\n        } else {\n            // If the drop zone is not valid then there is not need for us to\n            // try to process it. Instead we can just show an error to the user.\n            var message = getDropZoneError(dropZone);\n            Str.get_string('errorinvaliddate', 'calendar').then(function(string) {\n                Notification.exception({\n                    name: string,\n                    message: message || string\n                });\n            });\n        }\n\n        DataStore.clearAll();\n        clearAllDropZonesState();\n\n        e.preventDefault();\n    };\n\n    /**\n     * Clear the data store and remove the drag indicators from the UI\n     * when the drag event has finished.\n     */\n    var dragendHandler = function() {\n        DataStore.clearAll();\n        clearAllDropZonesState();\n    };\n\n    /**\n     * Re-render the drop zones in the new month to highlight\n     * which areas are or aren't acceptable to drop the calendar\n     * event.\n     */\n    var calendarMonthChangedHandler = function() {\n        updateAllDropZonesState();\n    };\n\n    return {\n        /**\n         * Initialise the event handlers for the drag events.\n         */\n        init: function() {\n            if (!registered) {\n                // These handlers are only added the first time the module\n                // is loaded because we don't want to have a new listener\n                // added each time the \"init\" function is called otherwise we'll\n                // end up with lots of stale handlers.\n                document.addEventListener('dragstart', dragstartHandler, false);\n                document.addEventListener('dragover', dragoverHandler, false);\n                document.addEventListener('dragleave', dragleaveHandler, false);\n                document.addEventListener('drop', dropHandler, false);\n                document.addEventListener('dragend', dragendHandler, false);\n                $('body').on(CalendarEvents.monthChanged, calendarMonthChangedHandler);\n                registered = true;\n            }\n        },\n    };\n});\n"],"names":["define","$","Notification","Str","CalendarEvents","DataStore","SELECTORS","ALL_CLASSES","INVALID_DROP_ZONE_CLASS","registered","getDropZoneFromEvent","e","dropZone","target","closest","length","isValidDropZone","dropTimestamp","attr","minTimestart","getMinTimestart","maxTimestart","getMaxTimestart","clearAllDropZonesState","find","each","index","removeClass","updateHoverState","hovered","count","getDurationDays","valid","addClass","VALID_HOVER_CLASS","nextDropZone","next","nextWeek","children","first","updateAllDropZonesState","dragstartHandler","draggableElement","eventId","minError","maxError","duration","setEventId","setDurationDays","setMinTimestart","setMaxTimestart","setMinError","setMaxError","dataTransfer","effectAllowed","dropEffect","setData","dragoverHandler","hasEventId","preventDefault","dragleaveHandler","dropHandler","clearAll","getEventId","eventElement","origin","trigger","moveEvent","message","getMinError","getMaxError","getDropZoneError","get_string","then","string","exception","name","dragendHandler","calendarMonthChangedHandler","init","document","addEventListener","on","monthChanged"],"mappings":"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"}