\n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n *\/\n\nimport Templates from 'core\/templates';\nimport Notification from 'core\/notification';\nexport default class NameListElement {\n el;\n names;\n rootElement;\n\n constructor(names, rootElement) {\n this.names = names;\n this.rootElement = rootElement;\n this.el = '[data-region=\"name-list\"]';\n this.addEventListeners();\n }\n\n reselectElement() {\n return this.rootElement.querySelector(this.el);\n }\n\n update(names) {\n if (!this.reselectElement()) {\n return;\n }\n const namesmap = names.map((name, i) => {\n const newName = {\n name: name,\n index: i\n };\n return newName;\n });\n const templatedata = {\n names: namesmap\n };\n Templates.render('mod_teachingtools\/names\/names', templatedata).then((html) => {\n this.reselectElement().innerHTML = html;\n return '';\n }).catch(Notification.exception);\n\n const removeNames = this.rootElement.querySelector('[data-action=\"remove-names\"]');\n if (removeNames) {\n if (names.length > 0) {\n removeNames.classList.remove('d-none');\n } else {\n removeNames.classList.add('d-none');\n }\n }\n\n const nameEditor = this.rootElement.querySelector('[data-action=\"names-editor\"]');\n\n if (nameEditor && document.activeElement !== nameEditor) {\n nameEditor.innerHTML = '';\n names.forEach((name) => {\n \/\/ Create a new div element\n const div = document.createElement(\"div\");\n div.innerHTML = name;\n nameEditor.appendChild(div);\n });\n }\n }\n\n removeTags(str) {\n if ((str === null) || (str === '')) {\n return false;\n } else {\n str = str.toString();\n return str.replace(\/(<([^>]+)>)\/ig, '');\n }\n }\n\n addEventListeners() {\n const nameForm = this.rootElement.querySelector('[data-region=\"name-form\"]');\n const advancedInput = this.rootElement.querySelector('[data-action=\"editadvanced\"]');\n if (advancedInput) {\n advancedInput.addEventListener('change', () => {\n if (advancedInput.checked) {\n this.addRemoveListeners();\n this.rootElement.querySelector('[data-region=\"advancededit\"]').classList.remove('d-none');\n this.rootElement.querySelector('[data-region=\"simpleedit\"]').classList.add('d-none');\n } else {\n this.rootElement.querySelector('[data-region=\"advancededit\"]').classList.add('d-none');\n this.rootElement.querySelector('[data-region=\"simpleedit\"]').classList.remove('d-none');\n }\n });\n }\n if (nameForm) {\n nameForm.addEventListener('submit', (e) => {\n e.preventDefault();\n const nameField = nameForm.querySelector('[data-region=\"name-input\"]');\n const value = nameField.value;\n if (value !== '') {\n nameField.value = '';\n nameField.focus();\n this.names.add(value);\n }\n });\n }\n const removeNames = this.rootElement.querySelector('[data-action=\"remove-names\"]');\n if (removeNames) {\n removeNames.addEventListener('click', () => {\n this.names.names = [];\n this.names.updateListeners();\n });\n }\n\n \/\/ Add paste event listener to the contenteditable.\n const nameEditor = this.rootElement.querySelector('[data-action=\"names-editor\"]');\n\n if (nameEditor) {\n nameEditor.innerHTML = '';\n this.names.names.forEach((name) => {\n \/\/ Create a new div element\n const div = document.createElement(\"div\");\n div.innerHTML = name;\n nameEditor.appendChild(div);\n });\n\n nameEditor.addEventListener('paste', (e) => {\n let paste = (e.clipboardData || window.clipboardData).getData('text');\n paste = this.removeTags(paste);\n if (!paste) {\n return;\n }\n let lines = paste.split(\/\\r?\\n\/);\n \/\/ Remove empty lines.\n lines = lines.filter(line => line.trim().length !== 0);\n\n \/\/ Fill the contenteditable with the pasted lines.\n let pastLines = lines.map(line => {\n return `${line}<\/div>`;\n });\n pastLines = pastLines.join('');\n\n const selection = window.getSelection();\n if (!selection.rangeCount) {\n return;\n }\n selection.deleteFromDocument();\n const newDiv = document.createElement('div');\n newDiv.innerHTML = pastLines;\n selection.getRangeAt(0).insertNode(newDiv);\n\n this.names.names = this.getLinesfromContentEditable(nameEditor);\n this.names.updateListeners();\n e.preventDefault();\n });\n\n \/\/ Add input event listener to the contenteditable.\n nameEditor.addEventListener('blur', (e) => {\n this.names.names = this.getLinesfromContentEditable(e.target);\n this.names.updateListeners();\n });\n }\n }\n\n getLinesfromContentEditable(contentEditableElement) {\n\n let newValue = '';\n let isOnFreshLine = true;\n\n \/**\n * Recursive function to navigate childNodes and build linebreaks with text\n * @param {object} childNodes The childNodes of the contentEditable element\n *\/\n function parseChildNodesForValueAndLines(childNodes) {\n for (let i = 0; i < childNodes.length; i++) {\n const childNode = childNodes[i];\n\n if (childNode.nodeName === 'BR') {\n \/\/ BRs are always line breaks which means the next loop is on a fresh line\n newValue += '\\n';\n isOnFreshLine = true;\n continue;\n }\n\n \/\/ We may or may not need to create a new line\n if (childNode.nodeName === 'DIV' && isOnFreshLine === false) {\n \/\/ Divs create new lines for themselves if they aren't already on one\n newValue += '\\n';\n }\n\n \/\/ Whether we created a new line or not, we'll use it for this content so the next loop will not be on a fresh line:\n isOnFreshLine = false;\n\n \/\/ Add the text content if this is a text node:\n if (childNode.nodeType === 3 && childNode.textContent) {\n newValue += childNode.textContent;\n }\n\n \/\/ If this node has children, get into them as well:\n parseChildNodesForValueAndLines(childNode.childNodes);\n }\n }\n\n \/\/ Parse the child nodes for HTML and newlines:\n parseChildNodesForValueAndLines(contentEditableElement.childNodes);\n \/\/ Clean out the empty lines.\n return newValue.split('\\n').map(name => name.trim()).filter(name => name !== '');\n }\n\n\n addRemoveListeners() {\n \/\/ Add the eventlisteners to the document.\n if (this.rootElement.dataset.removeListeners) {\n return;\n }\n this.rootElement.addEventListener('click', event => {\n\n \/\/ Show set from a card.\n const removeButton = event.target.closest('[data-action=\"remove-button\"]');\n if (removeButton) {\n event.preventDefault();\n this.names.remove(removeButton.dataset.index);\n }\n });\n this.rootElement.dataset.removeListeners = true;\n }\n}"],"names":["constructor","names","rootElement","el","addEventListeners","reselectElement","this","querySelector","update","templatedata","map","name","i","index","render","then","html","innerHTML","catch","Notification","exception","removeNames","length","classList","remove","add","nameEditor","document","activeElement","forEach","div","createElement","appendChild","removeTags","str","toString","replace","nameForm","advancedInput","addEventListener","checked","addRemoveListeners","e","preventDefault","nameField","value","focus","updateListeners","paste","clipboardData","window","getData","lines","split","filter","line","trim","pastLines","join","selection","getSelection","rangeCount","deleteFromDocument","newDiv","getRangeAt","insertNode","getLinesfromContentEditable","target","contentEditableElement","newValue","isOnFreshLine","parseChildNodesForValueAndLines","childNodes","childNode","nodeName","nodeType","textContent","dataset","removeListeners","event","removeButton","closest"],"mappings":"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"}