Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"discussion_nested_v2.min.js","sources":["../src/discussion_nested_v2.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 in nested v2 view.\n *\n * @module mod_forum/discussion_nested_v2\n * @copyright  2019 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport AutoRows from 'core/auto_rows';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as FormChangeChecker from 'core_form/changechecker';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport Discussion from 'mod_forum/discussion';\nimport InPageReply from 'mod_forum/inpage_reply';\nimport LockToggle from 'mod_forum/lock_toggle';\nimport FavouriteToggle from 'mod_forum/favourite_toggle';\nimport Pin from 'mod_forum/pin_toggle';\nimport Selectors from 'mod_forum/selectors';\nimport Subscribe from 'mod_forum/subscription_toggle';\n\nconst ANIMATION_DURATION = 150;\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getPostContainer = (element) => {\n    return element.closest(Selectors.post.post);\n};\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @param {Number} id Id of the post to find.\n * @return {Object} jQuery element\n */\nconst getPostContainerById = (element, id) => {\n    return element.find(`${Selectors.post.post}[data-post-id=${id}]`);\n};\n\n/**\n * Get the parent post container elements from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getParentPostContainers = (element) => {\n    return element.parents(Selectors.post.post);\n};\n\n/**\n * Get the post content container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getPostContentContainer = (postContainer) => {\n    return postContainer.children().not(Selectors.post.repliesContainer).find(Selectors.post.forumCoreContent);\n};\n\n/**\n * Get the in page reply container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyContainer = (postContainer) => {\n    return postContainer.children().filter(Selectors.post.inpageReplyContainer);\n};\n\n/**\n * Get the in page reply form element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyForm = (postContainer) => {\n    return getInPageReplyContainer(postContainer).find(Selectors.post.inpageReplyContent);\n};\n\n/**\n * Get the in page reply create (reply) button element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyCreateButton = (postContainer) => {\n    return getPostContentContainer(postContainer).find(Selectors.post.inpageReplyCreateButton);\n};\n\n/**\n * Get the replies visibility toggle container (show/hide replies button container) element\n * from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesVisibilityToggleContainer = (postContainer) => {\n    return postContainer.children(Selectors.post.repliesVisibilityToggleContainer);\n};\n\n/**\n * Get the replies container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesContainer = (postContainer) => {\n    return postContainer.children(Selectors.post.repliesContainer);\n};\n\n/**\n * Check if the post has any replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst hasReplies = (postContainer) => {\n    return getRepliesContainer(postContainer).children().length > 0;\n};\n\n/**\n * Get the show replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getShowRepliesButton = (replyVisibilityToggleContainer) => {\n    return replyVisibilityToggleContainer.find(Selectors.post.showReplies);\n};\n\n/**\n * Get the hide replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getHideRepliesButton = (replyVisibilityToggleContainer) => {\n    return replyVisibilityToggleContainer.find(Selectors.post.hideReplies);\n};\n\n/**\n * Check if the replies are visible.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst repliesVisible = (postContainer) => {\n    const repliesContainer = getRepliesContainer(postContainer);\n    return repliesContainer.is(':visible');\n};\n\n/**\n * Show the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst showReplies = (postContainer, postIdToSee = null) => {\n    const repliesContainer = getRepliesContainer(postContainer);\n    const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n    const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n    const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n    showButton.addClass('hidden');\n    hideButton.removeClass('hidden');\n\n    repliesContainer.slideDown({\n        duration: ANIMATION_DURATION,\n        queue: false,\n        complete: () => {\n            if (postIdToSee) {\n                const postContainerToSee = getPostContainerById(repliesContainer, postIdToSee);\n                if (postContainerToSee.length) {\n                    postContainerToSee[0].scrollIntoView();\n                }\n            }\n        }\n    }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n};\n\n/**\n * Hide the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst hideReplies = (postContainer) => {\n    const repliesContainer = getRepliesContainer(postContainer);\n    const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n    const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n    const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n    showButton.removeClass('hidden');\n    hideButton.addClass('hidden');\n\n    repliesContainer.slideUp({\n        duration: ANIMATION_DURATION,\n        queue: false\n    }).fadeOut(ANIMATION_DURATION);\n};\n\n/** Variable to hold the showInPageReplyForm function after it's built. */\nlet showInPageReplyForm = null;\n\n/**\n * Build the showInPageReplyForm function with the given additional template context.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template.\n * @return {Function}\n */\nconst buildShowInPageReplyFormFunction = (additionalTemplateContext) => {\n    /**\n     * Show the in page reply form in the given in page reply container. The form\n     * display will be animated.\n     *\n     * @param {Object} postContainer jQuery element for the post container\n     */\n    return async(postContainer) => {\n\n        const inPageReplyContainer = getInPageReplyContainer(postContainer);\n        const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n        const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n\n        if (!hasInPageReplyForm(inPageReplyContainer)) {\n            try {\n                const html = await renderInPageReplyTemplate(additionalTemplateContext, inPageReplyCreateButton, postContainer);\n                Templates.appendNodeContents(inPageReplyContainer, html, '');\n            } catch (e) {\n                Notification.exception(e);\n            }\n\n            FormChangeChecker.watchForm(postContainer[0].querySelector('form'));\n        }\n\n        inPageReplyCreateButton.fadeOut(ANIMATION_DURATION, () => {\n            const inPageReplyForm = getInPageReplyForm(postContainer);\n            inPageReplyForm.slideDown({\n                duration: ANIMATION_DURATION,\n                queue: false,\n                complete: () => {\n                    inPageReplyForm.find('textarea').focus();\n                }\n            }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n\n            if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n                repliesVisibilityToggleContainer.fadeIn(ANIMATION_DURATION);\n                hideReplies(postContainer);\n            }\n        });\n    };\n};\n\n/**\n * Hide the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst hideInPageReplyForm = (postContainer, postIdToSee = null) => {\n    const inPageReplyForm = getInPageReplyForm(postContainer);\n    const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n    const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n\n    if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n        repliesVisibilityToggleContainer.fadeOut(ANIMATION_DURATION);\n        if (!repliesVisible(postContainer)) {\n            showReplies(postContainer, postIdToSee);\n        }\n    }\n\n    inPageReplyForm.slideUp({\n        duration: ANIMATION_DURATION,\n        queue: false,\n        complete: () => {\n            inPageReplyCreateButton.fadeIn(ANIMATION_DURATION);\n        }\n    }).fadeOut(200);\n};\n\n/**\n * Check if the in page reply container contains the in page reply form.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @return {Bool}\n */\nconst hasInPageReplyForm = (inPageReplyContainer) => {\n    return inPageReplyContainer.find(Selectors.post.inpageReplyContent).length > 0;\n};\n\n/**\n * Render the template to generate the in page reply form HTML.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template\n * @param {Object} button jQuery element for the reply button that was clicked\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery promise\n */\nconst renderInPageReplyTemplate = (additionalTemplateContext, button, postContainer) => {\n    const postContentContainer = getPostContentContainer(postContainer);\n    const currentSubject = postContentContainer.find(Selectors.post.forumSubject).text();\n    const currentAuthorName = postContentContainer.find(Selectors.post.authorName).text();\n    const context = {\n        postid: postContainer.data('post-id'),\n        \"reply_url\": button.attr('data-href'),\n        sesskey: M.cfg.sesskey,\n        parentsubject: currentSubject,\n        parentauthorname: currentAuthorName,\n        canreplyprivately: button.data('can-reply-privately'),\n        postformat: InPageReply.CONTENT_FORMATS.MOODLE,\n        ...additionalTemplateContext\n    };\n\n    return Templates.render('mod_forum/inpage_reply_v2', context);\n};\n\n/**\n * Increment the total reply count in the show/hide replies buttons for the post.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst incrementTotalReplyCount = (postContainer) => {\n    getRepliesVisibilityToggleContainer(postContainer).find(Selectors.post.replyCount).each((index, element) => {\n        const currentCount = parseInt(element.innerText, 10);\n        element.innerText = currentCount + 1;\n    });\n};\n\n/**\n * Create all of the event listeners for the discussion.\n *\n * @param {Object} root jQuery element for the discussion container\n */\nconst registerEventListeners = (root) => {\n    CustomEvents.define(root, [CustomEvents.events.activate]);\n    // Auto expanding text area for in page reply.\n    AutoRows.init(root);\n\n    // Reply button is clicked.\n    root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCreateButton, (e, data) => {\n        data.originalEvent.preventDefault();\n        const postContainer = getPostContainer($(e.currentTarget));\n        showInPageReplyForm(postContainer);\n    });\n\n    // Cancel in page reply button.\n    root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCancelButton, (e, data) => {\n        data.originalEvent.preventDefault();\n        const postContainer = getPostContainer($(e.currentTarget));\n        hideInPageReplyForm(postContainer);\n    });\n\n    // Show replies button clicked.\n    root.on(CustomEvents.events.activate, Selectors.post.showReplies, (e, data) => {\n        data.originalEvent.preventDefault();\n        const postContainer = getPostContainer($(e.target));\n        showReplies(postContainer);\n    });\n\n    // Hide replies button clicked.\n    root.on(CustomEvents.events.activate, Selectors.post.hideReplies, (e, data) => {\n        data.originalEvent.preventDefault();\n        const postContainer = getPostContainer($(e.target));\n        hideReplies(postContainer);\n    });\n\n    // Post created with in page reply.\n    root.on(InPageReply.EVENTS.POST_CREATED, Selectors.post.inpageSubmitBtn, (e, newPostId) => {\n        const currentTarget = $(e.currentTarget);\n        const postContainer = getPostContainer(currentTarget);\n        const postContainers = getParentPostContainers(currentTarget);\n        hideInPageReplyForm(postContainer, newPostId);\n\n        postContainers.each((index, container) => {\n            incrementTotalReplyCount($(container));\n        });\n    });\n};\n\n/**\n * Initialise the javascript for the discussion in nested v2 display mode.\n *\n * @param {Object} root jQuery element for the discussion container\n * @param {Object} context Additional render context for the in page reply template\n */\nexport const init = (root, context) => {\n    // Build the showInPageReplyForm function with the additional render context.\n    showInPageReplyForm = buildShowInPageReplyFormFunction(context);\n    // Add discussion event listeners.\n    registerEventListeners(root);\n    // Initialise default discussion javascript (keyboard nav etc).\n    Discussion.init(root);\n    // Add in page reply javascript.\n    InPageReply.init(root);\n\n    // Initialise the settings menu javascript.\n    const discussionToolsContainer = root.find(Selectors.discussion.tools);\n    LockToggle.init(discussionToolsContainer, false);\n    FavouriteToggle.init(discussionToolsContainer, false, (toggleElement, response) => {\n        const newTargetState = response.userstate.favourited ? 0 : 1;\n        return toggleElement.data('targetstate', newTargetState);\n    });\n    Pin.init(discussionToolsContainer, false, (toggleElement, response) => {\n        const newTargetState = response.pinned ? 0 : 1;\n        return toggleElement.data('targetstate', newTargetState);\n    });\n    Subscribe.init(discussionToolsContainer, false, (toggleElement, response) => {\n        const newTargetState = response.userstate.subscribed ? 0 : 1;\n        toggleElement.data('targetstate', newTargetState);\n    });\n};\n"],"names":["getPostContainer","element","closest","Selectors","post","getPostContainerById","id","find","getPostContentContainer","postContainer","children","not","repliesContainer","forumCoreContent","getInPageReplyContainer","filter","inpageReplyContainer","getInPageReplyForm","inpageReplyContent","getInPageReplyCreateButton","inpageReplyCreateButton","getRepliesVisibilityToggleContainer","repliesVisibilityToggleContainer","getRepliesContainer","hasReplies","length","getShowRepliesButton","replyVisibilityToggleContainer","showReplies","getHideRepliesButton","hideReplies","repliesVisible","is","postIdToSee","showButton","hideButton","addClass","removeClass","slideDown","duration","queue","complete","postContainerToSee","scrollIntoView","css","fadeIn","slideUp","fadeOut","showInPageReplyForm","hideInPageReplyForm","inPageReplyForm","inPageReplyCreateButton","hasInPageReplyForm","inPageReplyContainer","renderInPageReplyTemplate","additionalTemplateContext","button","postContentContainer","currentSubject","forumSubject","text","currentAuthorName","authorName","context","postid","data","attr","sesskey","M","cfg","parentsubject","parentauthorname","canreplyprivately","postformat","InPageReply","CONTENT_FORMATS","MOODLE","Templates","render","registerEventListeners","root","define","CustomEvents","events","activate","init","on","e","originalEvent","preventDefault","currentTarget","inpageReplyCancelButton","target","EVENTS","POST_CREATED","inpageSubmitBtn","newPostId","postContainers","parents","each","index","container","replyCount","currentCount","parseInt","innerText","incrementTotalReplyCount","async","html","appendNodeContents","exception","FormChangeChecker","watchForm","querySelector","focus","discussionToolsContainer","discussion","tools","toggleElement","response","newTargetState","userstate","favourited","pinned","subscribed"],"mappings":"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"}