import Awesomplete from 'awesomplete'; /** * Find a parent element according to its tag and its attributes * * @param element Element where to start the search * @param tagName Expected parent tag name * @param attributes Associative array of expected attributes (name=>value). * * @returns Found element or null. */ function findParent(element, tagName, attributes) { const parentMatch = key => attributes[key] !== '' && element.getAttribute(key).indexOf(attributes[key]) !== -1; while (element) { if (element.tagName.toLowerCase() === tagName) { if (Object.keys(attributes).find(parentMatch)) { return element; } } element = element.parentElement; } return null; } /** * Ajax request to refresh the CSRF token. */ function refreshToken() { const xhr = new XMLHttpRequest(); xhr.open('GET', '?do=token'); xhr.onload = () => { const token = document.getElementById('token'); token.setAttribute('value', xhr.responseText); }; xhr.send(); } function createAwesompleteInstance(element, tags = []) { const awesome = new Awesomplete(Awesomplete.$(element)); // Tags are separated by a space awesome.filter = (text, input) => Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]); // Insert new selected tag in the input awesome.replace = (text) => { const before = awesome.input.value.match(/^.+ \s*|/)[0]; awesome.input.value = `${before}${text} `; }; // Highlight found items awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(/[^ ]*$/)[0]); // Don't display already selected items const reg = /(\w+) /g; let match; awesome.data = (item, input) => { while ((match = reg.exec(input))) { if (item === match[1]) { return ''; } } return item; }; awesome.minChars = 1; if (tags.length) { awesome.list = tags; } return awesome; } /** * Update awesomplete list of tag for all elements matching the given selector * * @param selector CSS selector * @param tags Array of tags * @param instances List of existing awesomplete instances */ function updateAwesompleteList(selector, tags, instances) { if (instances.length === 0) { // First load: create Awesomplete instances const elements = document.querySelectorAll(selector); [...elements].forEach((element) => { instances.push(createAwesompleteInstance(element, tags)); }); } else { // Update awesomplete tag list instances.map((item) => { item.list = tags; return item; }); } return instances; } /** * html_entities in JS * * @see http://stackoverflow.com/questions/18749591/encode-html-entities-in-javascript */ function htmlEntities(str) { return str.replace(/[\u00A0-\u9999<>&]/gim, i => `&#${i.charCodeAt(0)};`); } function activateFirefoxSocial(node) { const loc = location.href; const baseURL = loc.substring(0, loc.lastIndexOf('/') + 1); const data = { name: document.title, description: document.getElementById('translation-delete-link').innerHTML, author: 'Shaarli', version: '1.0.0', iconURL: `${baseURL}/images/favicon.ico`, icon32URL: `${baseURL}/images/favicon.ico`, icon64URL: `${baseURL}/images/favicon.ico`, shareURL: `${baseURL}?post=%{url}&title=%{title}&description=%{text}&source=firefoxsocialapi`, homepageURL: baseURL, }; node.setAttribute('data-service', JSON.stringify(data)); const activate = new CustomEvent('ActivateSocialFeature'); node.dispatchEvent(activate); } /** * Add the class 'hidden' to city options not attached to the current selected continent. * * @param cities List of