Proyectos de Subversion Moodle

Rev

Rev 5 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

{"version":3,"file":"script_point_view.min.js","sources":["../src/script_point_view.js"],"sourcesContent":["// This file is part of Moodle - https://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 * Module to display and manage reactions and difficulty tracks on course page.\n * @copyright  2020 Quentin Fombaron, 2021 Astor Bizard\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, ajax, notification) {\n\n    /**\n     * Call a function each time a course section is loaded.\n     * @param {Function} call Function to call.\n     */\n    function callOnModulesListLoad(call) {\n        call();\n\n        // The following listener is needed for the Tiles course format, where sections are loaded on demand.\n        $(document).ajaxComplete(function(event, xhr, settings) {\n            if (typeof (settings.data) !== 'string') {\n                return;\n            }\n            try {\n                var data = JSON.parse(settings.data);\n                if (data.length == 0 || typeof (data[0].methodname) === 'undefined') {\n                    return;\n                }\n                if (data[0].methodname == 'format_tiles_get_single_section_page_html' // Tile load.\n                    || data[0].methodname == 'format_tiles_log_tile_click') { // Tile load, cached.\n                    call();\n                }\n            } catch (e) {\n                // Something went wrong, it may not even be JSON. It is fine, this means it was not the call we were expecting.\n                return;\n            }\n        });\n    }\n\n    /**\n     * Set up difficulty tracks on course modules.\n     * @param {Array} difficultyLevels Array of difficulty tracks, one entry for each course module.\n     * @param {Array} trackColors Tracks colors, from block plugin configuration.\n     * @param {Number|null} cmid The course module ID, if this page is a module view.\n     */\n    function setUpDifficultyTracks(difficultyLevels, trackColors, cmid) {\n        difficultyLevels.forEach(function(module) {\n            var difficultyLevel = parseInt(module.difficultyLevel);\n            var title = '';\n            if (difficultyLevel > 0) {\n                var track = ['greentrack', 'bluetrack', 'redtrack', 'blacktrack'][difficultyLevel - 1];\n                title = M.util.get_string(track, 'block_point_view');\n            }\n            var $track = $('<div>', {\n                'class': 'block_point_view track',\n                'title': title,\n                'style': 'background-color: ' + trackColors[difficultyLevel] + ';'\n            });\n            // Decide where to put the track.\n            var $container = $('#module-' + module.id + ' .activitytitle');\n            if ($container.closest('.activity-grid').length) {\n                // Moodle 4.3+.\n                $container = $container.closest('.activity-grid');\n            }\n            if ($container.length === 0) {\n                // This seems to be a label.\n                $container = $('#module-' + module.id + ' .activity-item .description,' +\n                                '#module-' + module.id + ' .activity-item .activity-altcontent').first();\n            }\n\n            // Add the track.\n            if ($container.find('.block_point_view.track').length === 0) {\n                $container.prepend($track);\n            }\n            // If there is indentation, move the track after it.\n            $container.find('.mod-indent').after($track);\n\n            if (cmid === module.id) {\n                // This is a module page, add the track to the title.\n                $('.page-context-header').prepend($track);\n            }\n        });\n    }\n\n    /**\n     * Get a jQuery object in reaction zone for given module ID.\n     * @param {Number} moduleId Module ID.\n     * @param {String} selector (optional) Sub-selector.\n     * @return {jQuery} If selector was provided, the corresponding jQuery object within the reaction zone.\n     *  If not, the reaction zone jQuery object.\n     */\n    function $get(moduleId, selector) {\n        var $element = $('#module-' + moduleId + ' .block_point_view.reactions-container');\n        if (typeof (selector) === 'undefined') {\n            return $element;\n        } else {\n            return $element.find(selector);\n        }\n    }\n\n    // Enumeration of the possible reactions.\n    var Reactions = {\n            none: 0,\n            easy: 1,\n            better: 2,\n            hard: 3\n    };\n\n    // Array of Reaction of the user for the activity.\n    var reactionVotedArray = {};\n\n    /**\n     * Set up difficulty tracks on course modules.\n     * @param {Number} courseId Course ID.\n     * @param {Array} modulesWithReactions Array of reactions state, one entry for each course module with reactions enabled.\n     * @param {String} reactionsHtml HTML fragment for reactions.\n     * @param {Array} pixSrc Array of pictures sources for group images.\n     * @param {Number|null} cmid The course module ID, if this page is a module view.\n     */\n    function setUpReactions(courseId, modulesWithReactions, reactionsHtml, pixSrc, cmid) {\n        // For each selected module, create a reaction zone.\n        modulesWithReactions.forEach(function(module) {\n            var moduleId = parseInt(module.cmid);\n            var uservote = parseInt(module.uservote);\n\n            // Initialise reactionVotedArray.\n            reactionVotedArray[moduleId] = uservote;\n\n            if (module.cmid === cmid) {\n                // Simulate an activity row on course page (so we treat it the same for what's next).\n                $('<div id=\"module-' + moduleId + '\" class=\"activity-wrapper mr-5\" style=\"width: 165px;\">')\n                .insertAfter($('.header-actions-container'))\n                .prepend('<div class=\"activity-instance\">');\n            }\n\n            if ($('#module-' + moduleId).length === 1 && $get(moduleId).length === 0) {\n\n                // Add the reaction zone to the module.\n                var $module = $('#module-' + moduleId);\n                if ($module.is('.modtype_label')) {\n                    // Label.\n                    $module.find('.description, .activity-grid').first().before(reactionsHtml);\n                } else if ($module.find('.tiles-activity-container').length) {\n                    // Tiles format.\n                    $module.find('.tiles-activity-container').after(reactionsHtml);\n                } else {\n                    $module.find('.activity-instance').after(reactionsHtml);\n                }\n\n                // Setup reaction change.\n                var reactionsLock = false;\n                $get(moduleId, '.reaction img')\n                .click(function() {\n                    // Use a mutex to avoid query / display inconsistencies.\n                    // This is not a perfect mutex, but is actually enough for our needs.\n                    if (reactionsLock === false) {\n                        reactionsLock = true;\n                        reactionChange(courseId, moduleId, $(this).data('reactionname'))\n                        .always(function() {\n                            reactionsLock = false;\n                            updateGroupImgAndNb(moduleId, pixSrc);\n                        });\n                    }\n                });\n\n                // Initialize reactions state.\n                $get(moduleId, '.reactionnb').each(function() {\n                    var reactionName = $(this).data('reactionname');\n                    var reactionNb = parseInt(module['total' + reactionName]);\n                    updateReactionNb(moduleId, reactionName, reactionNb, uservote === Reactions[reactionName]);\n                });\n                updateGroupImgAndNb(moduleId, pixSrc);\n\n                // Setup animations.\n                setupReactionsAnimation(moduleId, pixSrc);\n            }\n        });\n    }\n\n    /**\n     * Manage a reaction change (user added, removed or updated their vote).\n     * @param {Number} courseId Course ID.\n     * @param {Number} moduleId Module ID.\n     * @param {String} reactionName The reaction being clicked.\n     * @returns {Promise} A promise, result of the change operations (ajax call and UI update).\n     */\n    function reactionChange(courseId, moduleId, reactionName) {\n\n        var reactionSelect = Reactions[reactionName];\n        var previousReaction = reactionVotedArray[moduleId];\n\n        // If the reaction being clicked is the current one, it is a vote remove.\n        var newVote = (reactionSelect === previousReaction) ? Reactions.none : reactionSelect;\n\n        return ajax.call([\n            {\n                methodname: 'block_point_view_update_db',\n                args: {\n                    func: 'update',\n                    courseid: courseId,\n                    cmid: moduleId,\n                    vote: newVote\n                }\n            }\n        ])[0]\n        .done(function() {\n            reactionVotedArray[moduleId] = newVote; // Set current reaction.\n            if (previousReaction !== Reactions.none) {\n                // User canceled their vote (or updated to another one).\n                var previousReactionName = ['', 'easy', 'better', 'hard'][previousReaction];\n                updateReactionNb(moduleId, previousReactionName, -1, false);\n            }\n            if (newVote !== Reactions.none) {\n                // User added or updated their vote.\n                updateReactionNb(moduleId, reactionName, +1, true); // Add new vote.\n            }\n        })\n        .fail(notification.exception);\n    }\n\n    /**\n     * Update the reactions group image and total number according to current votes.\n     * @param {Number} moduleId Module ID.\n     * @param {Array} pix Array of pictures sources for group images.\n     */\n    function updateGroupImgAndNb(moduleId, pix) {\n        // Build group image name.\n        var groupImg = 'group_';\n        var totalNb = 0;\n        $get(moduleId, '.reactionnb').each(function() {\n            var reactionNb = parseInt($(this).text());\n            if (reactionNb > 0) {\n                groupImg += $(this).data('reactionname').toUpperCase().charAt(0); // Add E, B or H.\n            }\n            totalNb += reactionNb;\n        });\n        // Modify the image source of the reaction group.\n        $get(moduleId, '.group_img').attr('src', pix[groupImg]);\n\n        // Update the total number of votes.\n        var $groupNbWrapper = $get(moduleId, '.group_nb');\n        var $groupNb = $groupNbWrapper.find('span');\n\n        $groupNb\n        .text(totalNb)\n        .attr('title', M.util.get_string('totalreactions', 'block_point_view', totalNb));\n\n        $groupNbWrapper\n        .toggleClass('invisible', totalNb === 0)\n        .toggleClass('voted', reactionVotedArray[moduleId] !== Reactions.none);\n\n        // Adjust the size to fit within a fixed space (useful for the green dot).\n        var digits = Math.min(('' + totalNb).length, 5);\n        $groupNb.css({\n            'right': Math.max(0.25 * (digits - 2), 0) + 'em',\n            'transform': 'scaleX(' + (1.0 + 0.03 * digits * digits - 0.35 * digits + 0.34) + ')'\n        });\n    }\n\n    /**\n     * Update a reaction number of votes.\n     * @param {Number} moduleId Module ID.\n     * @param {String} reactionName The reaction to update the number of.\n     * @param {Number} diff Difference to apply (e.g. +1 for adding a vote, -1 for removing a vote).\n     * @param {Boolean} isSelected Whether the reaction we are updating is the one now selected by user.\n     */\n    function updateReactionNb(moduleId, reactionName, diff, isSelected) {\n        var $reactionNb = $get(moduleId, '.reactionnb[data-reactionname=\"' + reactionName + '\"]');\n        var nbReaction = parseInt($reactionNb.text()) + diff;\n        $reactionNb\n        .text(nbReaction)\n        .toggleClass('nbselected', isSelected);\n\n        $get(moduleId, '.reaction img[data-reactionname=\"' + reactionName + '\"]')\n        .toggleClass('novote', nbReaction === 0);\n    }\n\n    /**\n     * Set up animations to swap between reactions preview and vote interface.\n     * @param {Number} moduleId Module ID.\n     */\n    function setupReactionsAnimation(moduleId) {\n\n        // Helpers to resize images for animations.\n        var reactionImageSizeForRatio = function(ratio) {\n            return {\n                top: 15 - (10 * ratio),\n                left: 10 - (10 * ratio),\n                height: 20 * ratio\n            };\n        };\n        var groupImageSizeForRatio = function(ratio) {\n            return {\n                left: -10 + (10 * ratio),\n                height: 20 * ratio\n            };\n        };\n\n        // Animation sequence to hide reactions preview and show vote interface.\n        var showReactions = function(moduleId) {\n            $get(moduleId, '.reactions').removeClass('invisible');\n\n            $get(moduleId, '.group_img')\n            .css({'pointer-events': 'none'})\n            .animate(groupImageSizeForRatio(0), 300)\n            .hide(0);\n\n            $get(moduleId, '.group_nb').delay(200).hide(300);\n\n            $('#module-' + moduleId + ' button[data-action=\"toggle-manual-completion\"],' +\n              '#module-' + moduleId + ' .activity-info .automatic-completion-conditions > span.badge:first-of-type,' +\n              '#module-' + moduleId + ' .activity-information [data-region=\"completionrequirements\"]')\n            .delay(200).queue(function(next) {\n                // Use opacity transition for a smooth hiding.\n                $(this).css({\n                    opacity: 0,\n                    transition: 'opacity 0.3s ease-in-out'\n                });\n                next();\n            }).delay(300).queue(function(next) {\n                // Actually make the element invisible to avoid accidental clicking on transparent element.\n                $(this).addClass('invisible');\n                next();\n            });\n\n            ['easy', 'better', 'hard'].forEach(function(reaction, index) {\n                var delay = 50 + 150 * index; // Easy: 50, better: 200, hard: 350.\n\n                $get(moduleId, '.reaction img[data-reactionname=\"' + reaction + '\"]')\n                .delay(delay).animate(reactionImageSizeForRatio(1), 300)\n                .css({'pointer-events': 'auto'});\n\n                $get(moduleId, '.reactionnb[data-reactionname=\"' + reaction + '\"]')\n                .delay(delay + 300)\n                .queue(function(next) {\n                    $(this).removeClass('invisible');\n                    next();\n                });\n            });\n        };\n\n        // Animation sequence to hide vote interface and show reaction preview.\n        var hideReactions = function(moduleId) {\n            ['hard', 'better', 'easy'].forEach(function(reaction, index) {\n                var delay = 50 + 250 * index; // Hard: 50, better: 300, easy: 550.\n                $get(moduleId, '.reaction img[data-reactionname=\"' + reaction + '\"]')\n                .css({'pointer-events': 'none'})\n                .delay(delay).animate(reactionImageSizeForRatio(0), 500);\n\n                $get(moduleId, '.reactionnb[data-reactionname=\"' + reaction + '\"]')\n                .delay(delay)\n                .queue(function(next) {\n                    $(this).addClass('invisible');\n                    next();\n                });\n            });\n\n            // Show the reaction group image with nice animation.\n            $get(moduleId, '.group_img')\n            .delay(500)\n            .show(0)\n            .animate(groupImageSizeForRatio(1), 300)\n            .queue(function(next) {\n                $get(moduleId, '.reactions').addClass('invisible');\n                next();\n            })\n            .css({'pointer-events': 'auto'});\n\n            $get(moduleId, '.group_nb').delay(600).show(0);\n\n            $('#module-' + moduleId + ' button[data-action=\"toggle-manual-completion\"],' +\n              '#module-' + moduleId + ' .activity-info .automatic-completion-conditions > span.badge:first-of-type,' +\n              '#module-' + moduleId + ' .activity-information [data-region=\"completionrequirements\"]')\n            .delay(600).queue(function(next) {\n                $(this).removeClass('invisible');\n                // Use opacity transition for a smooth showing back.\n                $(this).css({\n                    opacity: 1,\n                    transition: 'opacity 0.3s ease-in-out'\n                });\n                next();\n            });\n        };\n\n        // Setup some timeouts and locks to trigger animations.\n        var reactionsVisible = false;\n        var groupTimeout = null;\n        var reactionsTimeout = null;\n\n        var triggerHideReactions = function() {\n            reactionsTimeout = null;\n            reactionsVisible = false;\n            hideReactions(moduleId);\n        };\n\n        var triggerShowReactions = function() {\n            groupTimeout = null;\n            reactionsVisible = true;\n            showReactions(moduleId);\n            clearTimeout(reactionsTimeout);\n            reactionsTimeout = setTimeout(triggerHideReactions, 2000); // Hide reactions after 2 seconds if mouse is already out.\n        };\n\n        // Reactions preview interactions.\n        $get(moduleId, '.group_img')\n        .mouseover(function() {\n            $(this).stop().animate(groupImageSizeForRatio(1.15), 100); // Widen image a little on hover.\n            groupTimeout = setTimeout(triggerShowReactions, 300); // Show vote interface after 0.3s hover.\n        })\n        .mouseout(function() {\n            if (!reactionsVisible) {\n                // Cancel mouseover actions.\n                clearTimeout(groupTimeout);\n                $(this).stop().animate(groupImageSizeForRatio(1), 100);\n            }\n        })\n        .click(triggerShowReactions); // Show vote interface instantly on click.\n\n        // Reactions images interactions.\n        $get(moduleId, '.reaction img')\n        .mouseover(function() {\n            $(this).stop().animate(reactionImageSizeForRatio(2), 100); // Widen image a little on hover.\n        })\n        .mouseout(function() {\n            $(this).stop().animate(reactionImageSizeForRatio(1), 100);\n        });\n\n        // Vote interface zone interactions\n        $get(moduleId, '.reactions')\n        .mouseout(function() {\n            clearTimeout(reactionsTimeout);\n            reactionsTimeout = setTimeout(triggerHideReactions, 1000); // Hide vote interface after 1s out of it.\n        })\n        .mouseover(function() {\n            clearTimeout(reactionsTimeout);\n        });\n    }\n\n    return {\n        init: function(courseId) {\n\n            // Wait that the DOM is fully loaded.\n            $(function() {\n\n                var blockData = $('.block_point_view[data-blockdata]').data('blockdata');\n\n                var cmid = null; // If this page is a course module view, retrieve the module ID.\n                document.body.classList.forEach(function(bodyClass) {\n                    var matches = bodyClass.match(/cmid-(\\d+)/);\n                    cmid = matches ? matches[1] : cmid;\n                });\n\n                callOnModulesListLoad(function() {\n                    setUpDifficultyTracks(blockData.difficultylevels, blockData.trackcolors, cmid);\n                    setUpReactions(courseId, blockData.moduleswithreactions, blockData.reactionstemplate, blockData.pix, cmid);\n                });\n\n            });\n        }\n    };\n});"],"names":["define","$","ajax","notification","$get","moduleId","selector","$element","find","Reactions","none","easy","better","hard","reactionVotedArray","setUpReactions","courseId","modulesWithReactions","reactionsHtml","pixSrc","cmid","forEach","module","parseInt","uservote","insertAfter","prepend","length","$module","is","first","before","after","reactionsLock","click","reactionName","reactionSelect","previousReaction","newVote","call","methodname","args","func","courseid","vote","done","updateReactionNb","fail","exception","reactionChange","this","data","always","updateGroupImgAndNb","each","reactionNb","reactionImageSizeForRatio","ratio","top","left","height","groupImageSizeForRatio","showReactions","removeClass","css","animate","hide","delay","queue","next","opacity","transition","addClass","reaction","index","hideReactions","show","reactionsVisible","groupTimeout","reactionsTimeout","triggerHideReactions","triggerShowReactions","clearTimeout","setTimeout","mouseover","stop","mouseout","setupReactionsAnimation","pix","groupImg","totalNb","text","toUpperCase","charAt","attr","$groupNbWrapper","$groupNb","M","util","get_string","toggleClass","digits","Math","min","right","max","transform","diff","isSelected","$reactionNb","nbReaction","init","blockData","document","body","classList","bodyClass","matches","match","difficultyLevels","trackColors","difficultyLevel","title","track","$track","class","style","$container","id","closest","setUpDifficultyTracks","difficultylevels","trackcolors","moduleswithreactions","reactionstemplate","ajaxComplete","event","xhr","settings","JSON","parse","e"],"mappings":"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"}