Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"discussion.min.js","sources":["../src/discussion.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 * Module for viewing a discussion.\n *\n * @module     mod_forum/discussion\n * @copyright  2019 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n    'jquery',\n    'core/custom_interaction_events',\n    'mod_forum/selectors',\n    'core/pubsub',\n    'mod_forum/forum_events',\n    'core/str',\n    'core/notification',\n],\nfunction(\n    $,\n    CustomEvents,\n    Selectors,\n    PubSub,\n    ForumEvents,\n    String,\n    Notification\n) {\n\n    /**\n     * Set the focus on the previous post in the list. Previous post is calculated\n     * based on position in list as viewed top to bottom.\n     *\n     * @param {Object} currentPost The post that currently has focus\n     */\n    var focusPreviousPost = function(currentPost) {\n        // See if there is a previous sibling post.\n        var prevPost = currentPost.prev(Selectors.post.post);\n\n        if (prevPost.length) {\n            // The previous post might have replies that appear visually between\n            // it and the current post (see nested view) so if that's the case\n            // then the last reply will be the previous post in the list.\n            var replyPost = prevPost.find(Selectors.post.post).last();\n\n            if (replyPost.length) {\n                // Focus the last reply.\n                replyPost.focus();\n            } else {\n                // No replies so we can focus straight on the sibling.\n                prevPost.focus();\n            }\n        } else {\n            // If there are no siblings then jump up the tree to the parent\n            // post and focus the first parent post we find.\n            currentPost.parents(Selectors.post.post).first().focus();\n        }\n    };\n\n    /**\n     * Set the focus on the next post in the list. Previous post is calculated\n     * based on position in list as viewed top to bottom.\n     *\n     * @param {Object} currentPost The post that currently has focus\n     */\n    var focusNextPost = function(currentPost) {\n        // The next post in the visual list would be the first reply to this one\n        // so let's see if we have one.\n        var replyPost = currentPost.find(Selectors.post.post).first();\n\n        if (replyPost.length) {\n            // Got a reply.\n            replyPost.focus();\n        } else {\n            // If we don't have a reply then the next post in the visual list would\n            // be a sibling post (replying to the same parent).\n            var siblingPost = currentPost.next(Selectors.post.post);\n\n            if (siblingPost.length) {\n                siblingPost.focus();\n            } else {\n                // No siblings either. That means we're the lowest level reply in a thread\n                // so we need to walk back up the tree of posts and find an ancestor post that\n                // has a sibling post we can focus.\n                var parentPosts = currentPost.parents(Selectors.post.post).toArray();\n\n                for (var i = 0; i < parentPosts.length; i++) {\n                    var ancestorSiblingPost = $(parentPosts[i]).next(Selectors.post.post);\n\n                    if (ancestorSiblingPost.length) {\n                        ancestorSiblingPost.focus();\n                        break;\n                    }\n                }\n            }\n        }\n    };\n\n    /**\n     * Check if the element is inside the in page reply section.\n     *\n     * @param {Object} element The element to check\n     * @return {Boolean}\n     */\n    var isElementInInPageReplySection = function(element) {\n        var inPageReply = $(element).closest(Selectors.post.inpageReplyContent);\n        return inPageReply.length ? true : false;\n    };\n\n    /**\n     * Initialise the keyboard accessibility controls for the discussion.\n     *\n     * @param {Object} root The discussion root element\n     */\n    var initAccessibilityKeyboardNav = function(root) {\n        var posts = root.find(Selectors.post.post);\n\n        // Take each post action out of the tab index.\n        posts.each(function(index, post) {\n            var actions = $(post).find(Selectors.post.action);\n            var firstAction = actions.first();\n            actions.attr('tabindex', '-1');\n            firstAction.attr('tabindex', 0);\n        });\n\n        CustomEvents.define(root, [\n            CustomEvents.events.up,\n            CustomEvents.events.down,\n            CustomEvents.events.next,\n            CustomEvents.events.previous,\n            CustomEvents.events.home,\n            CustomEvents.events.end,\n        ]);\n\n        root.on(CustomEvents.events.up, function(e, data) {\n            var activeElement = document.activeElement;\n\n            if (isElementInInPageReplySection(activeElement)) {\n                // Focus is currently inside the in page reply section so don't move focus\n                // to another post.\n                return;\n            }\n\n            var focusPost = $(activeElement).closest(Selectors.post.post);\n\n            if (focusPost.length) {\n                focusPreviousPost(focusPost);\n            } else {\n                root.find(Selectors.post.post).first().focus();\n            }\n\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.down, function(e, data) {\n            var activeElement = document.activeElement;\n\n            if (isElementInInPageReplySection(activeElement)) {\n                // Focus is currently inside the in page reply section so don't move focus\n                // to another post.\n                return;\n            }\n\n            var focusPost = $(activeElement).closest(Selectors.post.post);\n\n            if (focusPost.length) {\n                focusNextPost(focusPost);\n            } else {\n                root.find(Selectors.post.post).first().focus();\n            }\n\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.home, function(e, data) {\n            if (isElementInInPageReplySection(document.activeElement)) {\n                // Focus is currently inside the in page reply section so don't move focus\n                // to another post.\n                return;\n            }\n            root.find(Selectors.post.post).first().focus();\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.end, function(e, data) {\n            if (isElementInInPageReplySection(document.activeElement)) {\n                // Focus is currently inside the in page reply section so don't move focus\n                // to another post.\n                return;\n            }\n            root.find(Selectors.post.post).last().focus();\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.next, Selectors.post.action, function(e, data) {\n            var currentAction = $(e.target);\n            var container = currentAction.closest(Selectors.post.actionsContainer);\n            var actions = container.find(Selectors.post.action);\n            var nextAction = currentAction.next(Selectors.post.action);\n\n            actions.attr('tabindex', '-1');\n\n            if (!nextAction.length) {\n                nextAction = actions.first();\n            }\n\n            nextAction.attr('tabindex', 0);\n            nextAction.focus();\n\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.previous, Selectors.post.action, function(e, data) {\n            var currentAction = $(e.target);\n            var container = currentAction.closest(Selectors.post.actionsContainer);\n            var actions = container.find(Selectors.post.action);\n            var nextAction = currentAction.prev(Selectors.post.action);\n\n            actions.attr('tabindex', '-1');\n\n            if (!nextAction.length) {\n                nextAction = actions.last();\n            }\n\n            nextAction.attr('tabindex', 0);\n            nextAction.focus();\n\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.home, Selectors.post.action, function(e, data) {\n            var currentAction = $(e.target);\n            var container = currentAction.closest(Selectors.post.actionsContainer);\n            var actions = container.find(Selectors.post.action);\n            var firstAction = actions.first();\n\n            actions.attr('tabindex', '-1');\n            firstAction.attr('tabindex', 0);\n            firstAction.focus();\n\n            e.stopPropagation();\n            data.originalEvent.preventDefault();\n        });\n\n        root.on(CustomEvents.events.end, Selectors.post.action, function(e, data) {\n            var currentAction = $(e.target);\n            var container = currentAction.closest(Selectors.post.actionsContainer);\n            var actions = container.find(Selectors.post.action);\n            var lastAction = actions.last();\n\n            actions.attr('tabindex', '-1');\n            lastAction.attr('tabindex', 0);\n            lastAction.focus();\n\n            e.stopPropagation();\n            data.originalEvent.preventDefault();\n        });\n\n        PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) {\n            var subscribed = data.subscriptionState;\n            var updateMessage = subscribed ? 'discussionsubscribed' : 'discussionunsubscribed';\n            String.get_string(updateMessage, \"forum\")\n                .then(function(s) {\n                    return Notification.addNotification({\n                        message: s,\n                        type: \"info\"\n                    });\n                })\n                .catch(Notification.exception);\n        });\n    };\n\n    return {\n        init: function(root) {\n            initAccessibilityKeyboardNav(root);\n        }\n    };\n});\n"],"names":["define","$","CustomEvents","Selectors","PubSub","ForumEvents","String","Notification","isElementInInPageReplySection","element","closest","post","inpageReplyContent","length","initAccessibilityKeyboardNav","root","find","each","index","actions","action","firstAction","first","attr","events","up","down","next","previous","home","end","on","e","data","activeElement","document","focusPost","currentPost","prevPost","prev","replyPost","last","focus","parents","focusPreviousPost","originalEvent","preventDefault","siblingPost","parentPosts","toArray","i","ancestorSiblingPost","focusNextPost","currentAction","target","actionsContainer","nextAction","stopPropagation","lastAction","subscribe","SUBSCRIPTION_TOGGLED","updateMessage","subscriptionState","get_string","then","s","addNotification","message","type","catch","exception","init"],"mappings":"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"}