Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"message_drawer_view_search.min.js","sources":["../src/message_drawer_view_search.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 * Controls the search page of the message drawer.\n *\n * @module     core_message/message_drawer_view_search\n * @copyright  2018 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    'core/notification',\n    'core/pubsub',\n    'core/str',\n    'core/templates',\n    'core_message/message_repository',\n    'core_message/message_drawer_events',\n],\nfunction(\n    $,\n    CustomEvents,\n    Notification,\n    PubSub,\n    Str,\n    Templates,\n    Repository,\n    Events\n) {\n\n    var MESSAGE_SEARCH_LIMIT = 50;\n    var USERS_SEARCH_LIMIT = 50;\n    var USERS_INITIAL_SEARCH_LIMIT = 3;\n\n    var SELECTORS = {\n        BLOCK_ICON_CONTAINER: '[data-region=\"block-icon-container\"]',\n        CANCEL_SEARCH_BUTTON: '[data-action=\"cancel-search\"]',\n        CONTACTS_CONTAINER: '[data-region=\"contacts-container\"]',\n        CONTACTS_LIST: '[data-region=\"contacts-container\"] [data-region=\"list\"]',\n        EMPTY_MESSAGE_CONTAINER: '[data-region=\"empty-message-container\"]',\n        LIST: '[data-region=\"list\"]',\n        LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n        LOADING_PLACEHOLDER: '[data-region=\"loading-placeholder\"]',\n        MESSAGES_LIST: '[data-region=\"messages-container\"] [data-region=\"list\"]',\n        MESSAGES_CONTAINER: '[data-region=\"messages-container\"]',\n        NON_CONTACTS_CONTAINER: '[data-region=\"non-contacts-container\"]',\n        NON_CONTACTS_LIST: '[data-region=\"non-contacts-container\"] [data-region=\"list\"]',\n        SEARCH_ICON_CONTAINER: '[data-region=\"search-icon-container\"]',\n        SEARCH_ACTION: '[data-action=\"search\"]',\n        SEARCH_INPUT: '[data-region=\"search-input\"]',\n        SEARCH_RESULTS_CONTAINER: '[data-region=\"search-results-container\"]',\n        LOAD_MORE_USERS: '[data-action=\"load-more-users\"]',\n        LOAD_MORE_MESSAGES: '[data-action=\"load-more-messages\"]',\n        BUTTON_TEXT: '[data-region=\"button-text\"]',\n        NO_RESULTS_CONTAINTER: '[data-region=\"no-results-container\"]',\n        ALL_CONTACTS_CONTAINER: '[data-region=\"all-contacts-container\"]'\n    };\n\n    var TEMPLATES = {\n        CONTACTS_LIST: 'core_message/message_drawer_contacts_list',\n        NON_CONTACTS_LIST: 'core_message/message_drawer_non_contacts_list',\n        MESSAGES_LIST: 'core_message/message_drawer_messages_list'\n    };\n\n    /**\n     * Get the logged in user id.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Number} User id.\n     */\n    var getLoggedInUserId = function(body) {\n        return body.attr('data-user-id');\n    };\n\n    /**\n     * Show the no messages container element.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} No messages container element.\n     */\n    var getEmptyMessageContainer = function(body) {\n        return body.find(SELECTORS.EMPTY_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Get the search loading icon.\n     *\n     * @param  {Object} header Search header container element.\n     * @return {Object} Loading icon element.\n     */\n    var getLoadingIconContainer = function(header) {\n        return header.find(SELECTORS.LOADING_ICON_CONTAINER);\n    };\n\n    /**\n     * Get the loading container element.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} Loading container element.\n     */\n    var getLoadingPlaceholder = function(body) {\n        return body.find(SELECTORS.LOADING_PLACEHOLDER);\n    };\n\n    /**\n     * Get the search icon container.\n     *\n     * @param  {Object} header Search header container element.\n     * @return {Object} Search icon container.\n     */\n    var getSearchIconContainer = function(header) {\n        return header.find(SELECTORS.SEARCH_ICON_CONTAINER);\n    };\n\n    /**\n     * Get the search input container.\n     *\n     * @param  {Object} header Search header container element.\n     * @return {Object} Search input container.\n     */\n    var getSearchInput = function(header) {\n        return header.find(SELECTORS.SEARCH_INPUT);\n    };\n\n    /**\n     * Get the search results container.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} Search results container.\n     */\n    var getSearchResultsContainer = function(body) {\n        return body.find(SELECTORS.SEARCH_RESULTS_CONTAINER);\n    };\n\n    /**\n     * Get the search contacts container.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} Search contacts container.\n     */\n    var getContactsContainer = function(body) {\n        return body.find(SELECTORS.CONTACTS_CONTAINER);\n    };\n\n    /**\n     * Get the search non contacts container.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} Search non contacts container.\n     */\n    var getNonContactsContainer = function(body) {\n        return body.find(SELECTORS.NON_CONTACTS_CONTAINER);\n    };\n\n    /**\n     * Get the search messages container.\n     *\n     * @param  {Object} body Search body container element.\n     * @return {Object} Search messages container.\n     */\n    var getMessagesContainer = function(body) {\n        return body.find(SELECTORS.MESSAGES_CONTAINER);\n    };\n\n\n    /**\n     * Show the messages empty container.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showEmptyMessage = function(body) {\n        getEmptyMessageContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages empty container.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideEmptyMessage = function(body) {\n        getEmptyMessageContainer(body).addClass('hidden');\n    };\n\n\n    /**\n     * Show the loading icon.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var showLoadingIcon = function(header) {\n        getLoadingIconContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the loading icon.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var hideLoadingIcon = function(header) {\n        getLoadingIconContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Show loading placeholder.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showLoadingPlaceholder = function(body) {\n        getLoadingPlaceholder(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide loading placeholder.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideLoadingPlaceholder = function(body) {\n        getLoadingPlaceholder(body).addClass('hidden');\n    };\n\n    /**\n     * Show search icon.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var showSearchIcon = function(header) {\n        getSearchIconContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide search icon.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var hideSearchIcon = function(header) {\n        getSearchIconContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Show search results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showSearchResults = function(body) {\n        getSearchResultsContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide search results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideSearchResults = function(body) {\n        getSearchResultsContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Show the no search results message.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showNoSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.ALL_CONTACTS_CONTAINER).addClass('hidden');\n        container.find(SELECTORS.MESSAGES_CONTAINER).addClass('hidden');\n        container.find(SELECTORS.NO_RESULTS_CONTAINTER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the no search results message.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideNoSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.ALL_CONTACTS_CONTAINER).removeClass('hidden');\n        container.find(SELECTORS.MESSAGES_CONTAINER).removeClass('hidden');\n        container.find(SELECTORS.NO_RESULTS_CONTAINTER).addClass('hidden');\n    };\n\n    /**\n     * Show the whole contacts results area.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showAllContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.ALL_CONTACTS_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the whole contacts results area.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideAllContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.ALL_CONTACTS_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Show the contacts results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.CONTACTS_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the contacts results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.CONTACTS_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Show the non contacts results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showNonContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.NON_CONTACTS_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the non contacts results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideNonContactsSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.NON_CONTACTS_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Show the messages results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var showMessagesSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.MESSAGES_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages results.\n     *\n     * @param {Object} body Search body container element.\n     */\n    var hideMessagesSearchResults = function(body) {\n        var container = getSearchResultsContainer(body);\n        container.find(SELECTORS.MESSAGES_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Disable the search input.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var disableSearchInput = function(header) {\n        getSearchInput(header).prop('disabled', true);\n    };\n\n    /**\n     * Enable the search input.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var enableSearchInput = function(header) {\n        getSearchInput(header).prop('disabled', false);\n    };\n\n    /**\n     * Clear the search input.\n     *\n     * @param {Object} header Search header container element.\n     */\n    var clearSearchInput = function(header) {\n        getSearchInput(header).val('');\n    };\n\n    /**\n     * Clear all search results\n     *\n     * @param {Object} body Search body container element.\n     */\n    var clearAllSearchResults = function(body) {\n        body.find(SELECTORS.CONTACTS_LIST).empty();\n        body.find(SELECTORS.NON_CONTACTS_LIST).empty();\n        body.find(SELECTORS.MESSAGES_LIST).empty();\n        hideNoSearchResults(body);\n        showAllContactsSearchResults(body);\n        showContactsSearchResults(body);\n        showNonContactsSearchResults(body);\n        showMessagesSearchResults(body);\n        showLoadMoreUsersButton(body);\n        showLoadMoreMessagesButton(body);\n    };\n\n    /**\n     * Update the body and header to indicate the search is loading.\n     *\n     * @param {Object} header Search header container element.\n     * @param {Object} body Search body container element.\n     */\n    var startLoading = function(header, body) {\n        hideSearchIcon(header);\n        hideEmptyMessage(body);\n        hideSearchResults(body);\n        showLoadingIcon(header);\n        showLoadingPlaceholder(body);\n        disableSearchInput(header);\n    };\n\n    /**\n     * Update the body and header to indicate the search has stopped loading.\n     *\n     * @param {Object} header Search header container element.\n     * @param {Object} body Search body container element.\n     */\n    var stopLoading = function(header, body) {\n        showSearchIcon(header);\n        hideEmptyMessage(body);\n        showSearchResults(body);\n        hideLoadingIcon(header);\n        hideLoadingPlaceholder(body);\n        enableSearchInput(header);\n    };\n\n    /**\n     * Show the more users loading icon.\n     *\n     * @param {Object} root The more users container element.\n     */\n    var showUsersLoadingIcon = function(root) {\n        var button = root.find(SELECTORS.LOAD_MORE_USERS);\n        button.prop('disabled', true);\n        button.find(SELECTORS.BUTTON_TEXT).addClass('hidden');\n        button.find(SELECTORS.LOADING_ICON_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the more users loading icon.\n     *\n     * @param {Object} root The more users container element.\n     */\n    var hideUsersLoadingIcon = function(root) {\n        var button = root.find(SELECTORS.LOAD_MORE_USERS);\n        button.prop('disabled', false);\n        button.find(SELECTORS.BUTTON_TEXT).removeClass('hidden');\n        button.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Show the load more users button.\n     *\n     * @param {Object} root The users container element.\n     */\n    var showLoadMoreUsersButton = function(root) {\n        root.find(SELECTORS.LOAD_MORE_USERS).removeClass('hidden');\n    };\n\n    /**\n     * Hide the load more users button.\n     *\n     * @param {Object} root The users container element.\n     */\n    var hideLoadMoreUsersButton = function(root) {\n        root.find(SELECTORS.LOAD_MORE_USERS).addClass('hidden');\n    };\n\n    /**\n     * Show the messages are loading icon.\n     *\n     * @param {Object} root Messages root element.\n     */\n    var showMessagesLoadingIcon = function(root) {\n        var button = root.find(SELECTORS.LOAD_MORE_MESSAGES);\n        button.prop('disabled', true);\n        button.find(SELECTORS.BUTTON_TEXT).addClass('hidden');\n        button.find(SELECTORS.LOADING_ICON_CONTAINER).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages are loading icon.\n     *\n     * @param {Object} root Messages root element.\n     */\n    var hideMessagesLoadingIcon = function(root) {\n        var button = root.find(SELECTORS.LOAD_MORE_MESSAGES);\n        button.prop('disabled', false);\n        button.find(SELECTORS.BUTTON_TEXT).removeClass('hidden');\n        button.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n    };\n\n    /**\n     * Show the load more messages button.\n     *\n     * @param  {Object} root The messages container element.\n     */\n    var showLoadMoreMessagesButton = function(root) {\n        root.find(SELECTORS.LOAD_MORE_MESSAGES).removeClass('hidden');\n    };\n\n    /**\n     * Hide the load more messages button.\n     *\n     * @param  {Object} root The messages container element.\n     */\n    var hideLoadMoreMessagesButton = function(root) {\n        root.find(SELECTORS.LOAD_MORE_MESSAGES).addClass('hidden');\n    };\n\n    /**\n     * Find a contact in the search results.\n     *\n     * @param  {Object} root Search results container element.\n     * @param  {Number} userId User id.\n     * @return {Object} User container element.\n     */\n    var findContact = function(root, userId) {\n        return root.find('[data-contact-user-id=\"' + userId + '\"]');\n    };\n\n    /**\n     * Add a contact to the search results.\n     *\n     * @param {Object} root Search results container.\n     * @param {Object} contact User in contacts list.\n     */\n    var addContact = function(root, contact) {\n        var nonContactsContainer = getNonContactsContainer(root);\n        var nonContact = findContact(nonContactsContainer, contact.userid);\n\n        if (nonContact.length) {\n            nonContact.remove();\n            var contactsContainer = getContactsContainer(root);\n            contactsContainer.removeClass('hidden');\n            contactsContainer.find(SELECTORS.LIST).append(nonContact);\n        }\n\n        if (!nonContactsContainer.find(SELECTORS.LIST).children().length) {\n            nonContactsContainer.addClass('hidden');\n        }\n    };\n\n    /**\n     * Remove a contact from the contacts results.\n     *\n     * @param {Object} root Search results container.\n     * @param {Object} userId Contact user id.\n     */\n    var removeContact = function(root, userId) {\n        var contactsContainer = getContactsContainer(root);\n        var contact = findContact(contactsContainer, userId);\n\n        if (contact.length) {\n            contact.remove();\n            var nonContactsContainer = getNonContactsContainer(root);\n            nonContactsContainer.removeClass('hidden');\n            nonContactsContainer.find(SELECTORS.LIST).append(contact);\n        }\n\n        if (!contactsContainer.find(SELECTORS.LIST).children().length) {\n            contactsContainer.addClass('hidden');\n        }\n    };\n\n    /**\n     * Show the contact is blocked icon.\n     *\n     * @param {Object} root Search results container.\n     * @param {Object} userId Contact user id.\n     */\n    var blockContact = function(root, userId) {\n        var contact = findContact(root, userId);\n        if (contact.length) {\n            contact.find(SELECTORS.BLOCK_ICON_CONTAINER).removeClass('hidden');\n        }\n    };\n\n    /**\n     * Hide the contact is blocked icon.\n     *\n     * @param {Object} root Search results container.\n     * @param {Object} userId Contact user id.\n     */\n    var unblockContact = function(root, userId) {\n        var contact = findContact(root, userId);\n        if (contact.length) {\n            contact.find(SELECTORS.BLOCK_ICON_CONTAINER).addClass('hidden');\n        }\n    };\n\n    /**\n     * Highlight words in search results.\n     *\n     * @param  {String} content HTML to search.\n     * @param  {String} searchText Search text.\n     * @return {String} searchText with search wrapped in matchtext span.\n     */\n    var highlightSearch = function(content, searchText) {\n        if (!content) {\n            return '';\n        }\n        var regex = new RegExp('(' + searchText + ')', 'gi');\n        return content.replace(regex, '<span class=\"matchtext\">$1</span>');\n    };\n\n\n    /**\n     * Render contacts in the contacts search results.\n     *\n     * @param {Object} root Search results container.\n     * @param {Array} contacts List of contacts.\n     * @return {Promise} Renderer promise.\n     */\n    var renderContacts = function(root, contacts) {\n        var container = getContactsContainer(root);\n        var frompanel = root.attr('data-in-panel');\n        var list = container.find(SELECTORS.LIST);\n\n        return Templates.render(TEMPLATES.CONTACTS_LIST, {contacts: contacts, frompanel: frompanel})\n            .then(function(html) {\n                list.append(html);\n                return html;\n            });\n    };\n\n    /**\n     * Render non contacts in the contacts search results.\n     *\n     * @param {Object} root Search results container.\n     * @param {Array} nonContacts List of non contacts.\n     * @return {Promise} Renderer promise.\n     */\n    var renderNonContacts = function(root, nonContacts) {\n        var container = getNonContactsContainer(root);\n        var frompanel = root.attr('data-in-panel');\n        var list = container.find(SELECTORS.LIST);\n\n        return Templates.render(TEMPLATES.NON_CONTACTS_LIST, {noncontacts: nonContacts, frompanel: frompanel})\n            .then(function(html) {\n                list.append(html);\n                return html;\n            });\n    };\n\n    /**\n     * Render messages in the messages search results.\n     *\n     * @param {Object} root Search results container.\n     * @param {Array} messages List of messages.\n     * @return {Promise} Renderer promise.\n     */\n    var renderMessages = function(root, messages) {\n        var container = getMessagesContainer(root);\n        var frompanel = root.attr('data-in-panel');\n        var list = container.find(SELECTORS.LIST);\n\n        return Templates.render(TEMPLATES.MESSAGES_LIST, {messages: messages, frompanel: frompanel})\n            .then(function(html) {\n                list.append(html);\n                return html;\n            });\n    };\n\n    /**\n     * Load more users from the repository and render the results into the users search results.\n     *\n     * @param  {Object} root Search results container.\n     * @param  {Number} loggedInUserId Current logged in user.\n     * @param  {String} text Search text.\n     * @param  {Number} limit Number of users to get.\n     * @param  {Number} offset Load users from\n     * @return {Object} jQuery promise\n     */\n    var loadMoreUsers = function(root, loggedInUserId, text, limit, offset) {\n        var loadedAll = false;\n        showUsersLoadingIcon(root);\n\n        return Repository.searchUsers(loggedInUserId, text, limit + 1, offset)\n            .then(function(results) {\n                var contacts = results.contacts;\n                var noncontacts = results.noncontacts;\n\n                if (contacts.length <= limit && noncontacts.length <= limit) {\n                    loadedAll = true;\n                    return {\n                        contacts: contacts,\n                        noncontacts: noncontacts\n                    };\n                } else {\n                    return {\n                        contacts: contacts.slice(0, limit),\n                        noncontacts: noncontacts.slice(0, limit)\n                    };\n                }\n            })\n            .then(function(results) {\n                var contactsCount = results.contacts.length;\n                var nonContactsCount = results.noncontacts.length;\n\n                if (contactsCount) {\n                    results.contacts.forEach(function(contact) {\n                        contact.highlight = highlightSearch(contact.fullname, text);\n                    });\n                }\n\n                if (nonContactsCount) {\n                    results.noncontacts.forEach(function(contact) {\n                        contact.highlight = highlightSearch(contact.fullname, text);\n                    });\n                }\n\n                return $.when(\n                    contactsCount ? renderContacts(root, results.contacts) : true,\n                    nonContactsCount ? renderNonContacts(root, results.noncontacts) : true\n                )\n                .then(function() {\n                    return {\n                        contactsCount: contactsCount,\n                        nonContactsCount: nonContactsCount\n                    };\n                });\n            })\n            .then(function(counts) {\n                hideUsersLoadingIcon(root);\n\n                if (loadedAll) {\n                    hideLoadMoreUsersButton(root);\n                }\n\n                return counts;\n            })\n            .catch(function(error) {\n                hideUsersLoadingIcon(root);\n                // Rethrow error for other handlers.\n                throw error;\n            });\n    };\n\n    /**\n     * Load more messages from the repository and render the results into the messages search results.\n     *\n     * @param  {Object} root Search results container.\n     * @param  {Number} loggedInUserId Current logged in user.\n     * @param  {String} text Search text.\n     * @param  {Number} limit Number of messages to get.\n     * @param  {Number} offset Load messages from\n     * @return {Object} jQuery promise\n     */\n    var loadMoreMessages = function(root, loggedInUserId, text, limit, offset) {\n        var loadedAll = false;\n        showMessagesLoadingIcon(root);\n\n        return Repository.searchMessages(loggedInUserId, text, limit + 1, offset)\n            .then(function(results) {\n                var messages = results.contacts;\n\n                if (messages.length <= limit) {\n                    loadedAll = true;\n                    return messages;\n                } else {\n                    return messages.slice(0, limit);\n                }\n            })\n            .then(function(messages) {\n                if (messages.length) {\n                    messages.forEach(function(message) {\n                        message.lastmessage = highlightSearch(message.lastmessage, text);\n                    });\n                    return renderMessages(root, messages)\n                        .then(function() {\n                            return messages.length;\n                        });\n                } else {\n                    return messages.length;\n                }\n            })\n            .then(function(count) {\n                hideMessagesLoadingIcon(root);\n\n                if (loadedAll) {\n                    hideLoadMoreMessagesButton(root);\n                }\n\n                return count;\n            })\n            .catch(function(error) {\n                hideMessagesLoadingIcon(root);\n                // Rethrow error for other handlers.\n                throw error;\n            });\n    };\n\n    /**\n     * Search for users and messages.\n     *\n     * @param {Object} header Search header container element.\n     * @param {Object} body Search body container element.\n     * @param {String} searchText Search text.\n     * @param {Number} usersLimit The users limit.\n     * @param {Number} usersOffset The users offset.\n     * @param {Number} messagesLimit The message limit.\n     * @param {Number} messagesOffset The message offset.\n     * @return {Object} jQuery promise\n     */\n    var search = function(header, body, searchText, usersLimit, usersOffset, messagesLimit, messagesOffset) {\n        var loggedInUserId = getLoggedInUserId(body);\n        startLoading(header, body);\n        clearAllSearchResults(body);\n\n        return $.when(\n            loadMoreUsers(body, loggedInUserId, searchText, usersLimit, usersOffset),\n            loadMoreMessages(body, loggedInUserId, searchText, messagesLimit, messagesOffset)\n        )\n        .then(function(userCounts, messagesCount) {\n            var contactsCount = userCounts.contactsCount;\n            var nonContactsCount = userCounts.nonContactsCount;\n\n            stopLoading(header, body);\n\n            if (!contactsCount && !nonContactsCount && !messagesCount) {\n                showNoSearchResults(body);\n            } else {\n                if (!contactsCount && !nonContactsCount) {\n                    hideAllContactsSearchResults(body);\n                } else {\n                    if (!contactsCount) {\n                        hideContactsSearchResults(body);\n                    }\n\n                    if (!nonContactsCount) {\n                        hideNonContactsSearchResults(body);\n                    }\n                }\n\n                if (!messagesCount) {\n                    hideMessagesSearchResults(body);\n                }\n            }\n\n            return;\n        });\n    };\n\n\n    /**\n     * Listen to and handle events for searching.\n     *\n     * @param {Object} header Search header container element.\n     * @param {Object} body Search body container element.\n     */\n    var registerEventListeners = function(header, body) {\n        var loggedInUserId = getLoggedInUserId(body);\n        var searchInput = getSearchInput(header);\n        var searchText = '';\n        var messagesOffset = 0;\n        var usersOffset = 0;\n\n        var searchEventHandler = function(e, data) {\n            searchText = searchInput.val().trim();\n\n            if (searchText !== '') {\n                messagesOffset = 0;\n                usersOffset = 0;\n                search(\n                    header,\n                    body,\n                    searchText,\n                    USERS_INITIAL_SEARCH_LIMIT,\n                    usersOffset,\n                    MESSAGE_SEARCH_LIMIT,\n                    messagesOffset\n                )\n                .then(function() {\n                    searchInput.focus();\n                    usersOffset = usersOffset + USERS_INITIAL_SEARCH_LIMIT;\n                    messagesOffset = messagesOffset + MESSAGE_SEARCH_LIMIT;\n                    return;\n                })\n                .catch(Notification.exception);\n            }\n\n            data.originalEvent.preventDefault();\n        };\n\n        CustomEvents.define(searchInput, [CustomEvents.events.enter]);\n        CustomEvents.define(header, [CustomEvents.events.activate]);\n        CustomEvents.define(body, [CustomEvents.events.activate]);\n\n        searchInput.on(CustomEvents.events.enter, searchEventHandler);\n\n        header.on(CustomEvents.events.activate, SELECTORS.SEARCH_ACTION, searchEventHandler);\n\n        body.on(CustomEvents.events.activate, SELECTORS.LOAD_MORE_MESSAGES, function(e, data) {\n            if (searchText !== '') {\n                loadMoreMessages(body, loggedInUserId, searchText, MESSAGE_SEARCH_LIMIT, messagesOffset)\n                    .then(function() {\n                        messagesOffset = messagesOffset + MESSAGE_SEARCH_LIMIT;\n                        return;\n                    })\n                    .catch(Notification.exception);\n            }\n            data.originalEvent.preventDefault();\n        });\n\n        body.on(CustomEvents.events.activate, SELECTORS.LOAD_MORE_USERS, function(e, data) {\n            if (searchText !== '') {\n                loadMoreUsers(body, loggedInUserId, searchText, USERS_SEARCH_LIMIT, usersOffset)\n                    .then(function() {\n                        usersOffset = usersOffset + USERS_SEARCH_LIMIT;\n                        return;\n                    })\n                    .catch(Notification.exception);\n            }\n            data.originalEvent.preventDefault();\n        });\n\n        header.on(CustomEvents.events.activate, SELECTORS.CANCEL_SEARCH_BUTTON, function() {\n            clearSearchInput(header);\n            showEmptyMessage(body);\n            showSearchIcon(header);\n            hideSearchResults(body);\n            hideLoadingIcon(header);\n            hideLoadingPlaceholder(body);\n            usersOffset = 0;\n            messagesOffset = 0;\n        });\n\n        PubSub.subscribe(Events.CONTACT_ADDED, function(userId) {\n            addContact(body, userId);\n        });\n\n        PubSub.subscribe(Events.CONTACT_REMOVED, function(userId) {\n            removeContact(body, userId);\n        });\n\n        PubSub.subscribe(Events.CONTACT_BLOCKED, function(userId) {\n            blockContact(body, userId);\n        });\n\n        PubSub.subscribe(Events.CONTACT_UNBLOCKED, function(userId) {\n            unblockContact(body, userId);\n        });\n    };\n\n    /**\n     * Setup the search page.\n     *\n     * @param {string} namespace The route namespace.\n     * @param {Object} header Contacts header container element.\n     * @param {Object} body Contacts body container element.\n     * @return {Object} jQuery promise\n     */\n    var show = function(namespace, header, body) {\n        if (!body.attr('data-init')) {\n            registerEventListeners(header, body);\n            body.attr('data-init', true);\n        }\n        var searchInput = getSearchInput(header);\n        searchInput.focus();\n\n        return $.Deferred().resolve().promise();\n    };\n\n    /**\n     * String describing this page used for aria-labels.\n     *\n     * @param {string} namespace The route namespace.\n     * @param {Object} header Contacts header container element.\n     * @return {Object} jQuery promise\n     */\n    var description = function(namespace, header) {\n        if (typeof header !== 'object') {\n            return Str.get_string('messagedrawerviewsearch', 'core_message');\n        }\n        var searchInput = getSearchInput(header);\n        var searchText = searchInput.val().trim();\n        return Str.get_string('messagedrawerviewsearch', 'core_message', searchText);\n    };\n\n    return {\n        show: show,\n        description: description\n    };\n});\n"],"names":["define","$","CustomEvents","Notification","PubSub","Str","Templates","Repository","Events","SELECTORS","TEMPLATES","getLoggedInUserId","body","attr","getEmptyMessageContainer","find","getLoadingIconContainer","header","getLoadingPlaceholder","getSearchIconContainer","getSearchInput","getSearchResultsContainer","getContactsContainer","getNonContactsContainer","hideEmptyMessage","addClass","hideLoadingIcon","hideLoadingPlaceholder","showSearchIcon","removeClass","hideSearchResults","clearAllSearchResults","empty","container","hideNoSearchResults","showAllContactsSearchResults","showContactsSearchResults","showNonContactsSearchResults","showMessagesSearchResults","showLoadMoreUsersButton","showLoadMoreMessagesButton","startLoading","hideSearchIcon","showLoadingIcon","showLoadingPlaceholder","prop","disableSearchInput","stopLoading","showSearchResults","enableSearchInput","hideUsersLoadingIcon","root","button","hideMessagesLoadingIcon","findContact","userId","highlightSearch","content","searchText","regex","RegExp","replace","renderMessages","messages","frompanel","list","render","then","html","append","loadMoreUsers","loggedInUserId","text","limit","offset","loadedAll","showUsersLoadingIcon","searchUsers","results","contacts","noncontacts","length","slice","contactsCount","nonContactsCount","forEach","contact","highlight","fullname","when","renderContacts","nonContacts","renderNonContacts","counts","hideLoadMoreUsersButton","catch","error","loadMoreMessages","showMessagesLoadingIcon","searchMessages","message","lastmessage","count","hideLoadMoreMessagesButton","search","usersLimit","usersOffset","messagesLimit","messagesOffset","userCounts","messagesCount","hideContactsSearchResults","hideNonContactsSearchResults","hideAllContactsSearchResults","hideMessagesSearchResults","showNoSearchResults","registerEventListeners","searchInput","searchEventHandler","e","data","val","trim","focus","exception","originalEvent","preventDefault","events","enter","activate","on","clearSearchInput","showEmptyMessage","subscribe","CONTACT_ADDED","nonContactsContainer","nonContact","userid","remove","contactsContainer","children","addContact","CONTACT_REMOVED","removeContact","CONTACT_BLOCKED","blockContact","CONTACT_UNBLOCKED","unblockContact","show","namespace","Deferred","resolve","promise","description","get_string"],"mappings":"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"}