diff options
Diffstat (limited to 'assets/default/js')
-rw-r--r-- | assets/default/js/base.js | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/assets/default/js/base.js b/assets/default/js/base.js index be986ae0..dd532bb7 100644 --- a/assets/default/js/base.js +++ b/assets/default/js/base.js | |||
@@ -1,4 +1,5 @@ | |||
1 | import Awesomplete from 'awesomplete'; | 1 | import Awesomplete from 'awesomplete'; |
2 | import he from 'he'; | ||
2 | 3 | ||
3 | /** | 4 | /** |
4 | * Find a parent element according to its tag and its attributes | 5 | * Find a parent element according to its tag and its attributes |
@@ -41,19 +42,21 @@ function refreshToken(basePath, callback) { | |||
41 | xhr.send(); | 42 | xhr.send(); |
42 | } | 43 | } |
43 | 44 | ||
44 | function createAwesompleteInstance(element, tags = []) { | 45 | function createAwesompleteInstance(element, separator, tags = []) { |
45 | const awesome = new Awesomplete(Awesomplete.$(element)); | 46 | const awesome = new Awesomplete(Awesomplete.$(element)); |
46 | // Tags are separated by a space | 47 | |
47 | awesome.filter = (text, input) => Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]); | 48 | // Tags are separated by separator |
49 | awesome.filter = (text, input) => Awesomplete.FILTER_CONTAINS(text, input.match(new RegExp(`[^${separator}]*$`))[0]); | ||
48 | // Insert new selected tag in the input | 50 | // Insert new selected tag in the input |
49 | awesome.replace = (text) => { | 51 | awesome.replace = (text) => { |
50 | const before = awesome.input.value.match(/^.+ \s*|/)[0]; | 52 | const before = awesome.input.value.match(new RegExp(`^.+${separator}+|`))[0]; |
51 | awesome.input.value = `${before}${text} `; | 53 | awesome.input.value = `${before}${text}${separator}`; |
52 | }; | 54 | }; |
53 | // Highlight found items | 55 | // Highlight found items |
54 | awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(/[^ ]*$/)[0]); | 56 | awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(new RegExp(`[^${separator}]*$`))[0]); |
55 | // Don't display already selected items | 57 | // Don't display already selected items |
56 | const reg = /(\w+) /g; | 58 | // WARNING: pseudo classes does not seem to work with string litterals... |
59 | const reg = new RegExp(`([^${separator}]+)${separator}`, 'g'); | ||
57 | let match; | 60 | let match; |
58 | awesome.data = (item, input) => { | 61 | awesome.data = (item, input) => { |
59 | while ((match = reg.exec(input))) { | 62 | while ((match = reg.exec(input))) { |
@@ -77,13 +80,14 @@ function createAwesompleteInstance(element, tags = []) { | |||
77 | * @param selector CSS selector | 80 | * @param selector CSS selector |
78 | * @param tags Array of tags | 81 | * @param tags Array of tags |
79 | * @param instances List of existing awesomplete instances | 82 | * @param instances List of existing awesomplete instances |
83 | * @param separator Tags separator character | ||
80 | */ | 84 | */ |
81 | function updateAwesompleteList(selector, tags, instances) { | 85 | function updateAwesompleteList(selector, tags, instances, separator) { |
82 | if (instances.length === 0) { | 86 | if (instances.length === 0) { |
83 | // First load: create Awesomplete instances | 87 | // First load: create Awesomplete instances |
84 | const elements = document.querySelectorAll(selector); | 88 | const elements = document.querySelectorAll(selector); |
85 | [...elements].forEach((element) => { | 89 | [...elements].forEach((element) => { |
86 | instances.push(createAwesompleteInstance(element, tags)); | 90 | instances.push(createAwesompleteInstance(element, separator, tags)); |
87 | }); | 91 | }); |
88 | } else { | 92 | } else { |
89 | // Update awesomplete tag list | 93 | // Update awesomplete tag list |
@@ -96,15 +100,6 @@ function updateAwesompleteList(selector, tags, instances) { | |||
96 | } | 100 | } |
97 | 101 | ||
98 | /** | 102 | /** |
99 | * html_entities in JS | ||
100 | * | ||
101 | * @see http://stackoverflow.com/questions/18749591/encode-html-entities-in-javascript | ||
102 | */ | ||
103 | function htmlEntities(str) { | ||
104 | return str.replace(/[\u00A0-\u9999<>&]/gim, (i) => `&#${i.charCodeAt(0)};`); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Add the class 'hidden' to city options not attached to the current selected continent. | 103 | * Add the class 'hidden' to city options not attached to the current selected continent. |
109 | * | 104 | * |
110 | * @param cities List of <option> elements | 105 | * @param cities List of <option> elements |
@@ -222,6 +217,8 @@ function init(description) { | |||
222 | 217 | ||
223 | (() => { | 218 | (() => { |
224 | const basePath = document.querySelector('input[name="js_base_path"]').value; | 219 | const basePath = document.querySelector('input[name="js_base_path"]').value; |
220 | const tagsSeparatorElement = document.querySelector('input[name="tags_separator"]'); | ||
221 | const tagsSeparator = tagsSeparatorElement ? tagsSeparatorElement.value || ' ' : ' '; | ||
225 | 222 | ||
226 | /** | 223 | /** |
227 | * Handle responsive menu. | 224 | * Handle responsive menu. |
@@ -302,7 +299,8 @@ function init(description) { | |||
302 | const deleteLinks = document.querySelectorAll('.confirm-delete'); | 299 | const deleteLinks = document.querySelectorAll('.confirm-delete'); |
303 | [...deleteLinks].forEach((deleteLink) => { | 300 | [...deleteLinks].forEach((deleteLink) => { |
304 | deleteLink.addEventListener('click', (event) => { | 301 | deleteLink.addEventListener('click', (event) => { |
305 | if (!confirm(document.getElementById('translation-delete-link').innerHTML)) { | 302 | const type = event.currentTarget.getAttribute('data-type') || 'link'; |
303 | if (!confirm(document.getElementById(`translation-delete-${type}`).innerHTML)) { | ||
306 | event.preventDefault(); | 304 | event.preventDefault(); |
307 | } | 305 | } |
308 | }); | 306 | }); |
@@ -569,7 +567,7 @@ function init(description) { | |||
569 | input.setAttribute('name', totag); | 567 | input.setAttribute('name', totag); |
570 | input.setAttribute('value', totag); | 568 | input.setAttribute('value', totag); |
571 | findParent(input, 'div', { class: 'rename-tag-form' }).style.display = 'none'; | 569 | findParent(input, 'div', { class: 'rename-tag-form' }).style.display = 'none'; |
572 | block.querySelector('a.tag-link').innerHTML = htmlEntities(totag); | 570 | block.querySelector('a.tag-link').innerHTML = he.encode(totag); |
573 | block | 571 | block |
574 | .querySelector('a.tag-link') | 572 | .querySelector('a.tag-link') |
575 | .setAttribute('href', `${basePath}/?searchtags=${encodeURIComponent(totag)}`); | 573 | .setAttribute('href', `${basePath}/?searchtags=${encodeURIComponent(totag)}`); |
@@ -582,7 +580,7 @@ function init(description) { | |||
582 | 580 | ||
583 | // Refresh awesomplete values | 581 | // Refresh awesomplete values |
584 | existingTags = existingTags.map((tag) => (tag === fromtag ? totag : tag)); | 582 | existingTags = existingTags.map((tag) => (tag === fromtag ? totag : tag)); |
585 | awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes); | 583 | awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes, tagsSeparator); |
586 | } | 584 | } |
587 | }; | 585 | }; |
588 | xhr.send(`renametag=1&fromtag=${fromtagUrl}&totag=${encodeURIComponent(totag)}&token=${refreshedToken}`); | 586 | xhr.send(`renametag=1&fromtag=${fromtagUrl}&totag=${encodeURIComponent(totag)}&token=${refreshedToken}`); |
@@ -622,14 +620,14 @@ function init(description) { | |||
622 | refreshToken(basePath); | 620 | refreshToken(basePath); |
623 | 621 | ||
624 | existingTags = existingTags.filter((tagItem) => tagItem !== tag); | 622 | existingTags = existingTags.filter((tagItem) => tagItem !== tag); |
625 | awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes); | 623 | awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes, tagsSeparator); |
626 | } | 624 | } |
627 | }); | 625 | }); |
628 | }); | 626 | }); |
629 | 627 | ||
630 | const autocompleteFields = document.querySelectorAll('input[data-multiple]'); | 628 | const autocompleteFields = document.querySelectorAll('input[data-multiple]'); |
631 | [...autocompleteFields].forEach((autocompleteField) => { | 629 | [...autocompleteFields].forEach((autocompleteField) => { |
632 | awesomepletes.push(createAwesompleteInstance(autocompleteField)); | 630 | awesomepletes.push(createAwesompleteInstance(autocompleteField, tagsSeparator)); |
633 | }); | 631 | }); |
634 | 632 | ||
635 | const exportForm = document.querySelector('#exportform'); | 633 | const exportForm = document.querySelector('#exportform'); |
@@ -642,4 +640,33 @@ function init(description) { | |||
642 | }); | 640 | }); |
643 | }); | 641 | }); |
644 | } | 642 | } |
643 | |||
644 | const bulkCreationButton = document.querySelector('.addlink-batch-show-more-block'); | ||
645 | if (bulkCreationButton != null) { | ||
646 | const toggleBulkCreationVisibility = (showMoreBlockElement, formElement) => { | ||
647 | if (bulkCreationButton.classList.contains('pure-u-0')) { | ||
648 | showMoreBlockElement.classList.remove('pure-u-0'); | ||
649 | formElement.classList.add('pure-u-0'); | ||
650 | } else { | ||
651 | showMoreBlockElement.classList.add('pure-u-0'); | ||
652 | formElement.classList.remove('pure-u-0'); | ||
653 | } | ||
654 | }; | ||
655 | |||
656 | const bulkCreationForm = document.querySelector('.addlink-batch-form-block'); | ||
657 | |||
658 | toggleBulkCreationVisibility(bulkCreationButton, bulkCreationForm); | ||
659 | bulkCreationButton.querySelector('a').addEventListener('click', (e) => { | ||
660 | e.preventDefault(); | ||
661 | toggleBulkCreationVisibility(bulkCreationButton, bulkCreationForm); | ||
662 | }); | ||
663 | |||
664 | // Force to send falsy value if the checkbox is not checked. | ||
665 | const privateButton = bulkCreationForm.querySelector('input[type="checkbox"][name="private"]'); | ||
666 | const privateHiddenButton = bulkCreationForm.querySelector('input[type="hidden"][name="private"]'); | ||
667 | privateButton.addEventListener('click', () => { | ||
668 | privateHiddenButton.disabled = !privateHiddenButton.disabled; | ||
669 | }); | ||
670 | privateHiddenButton.disabled = privateButton.checked; | ||
671 | } | ||
645 | })(); | 672 | })(); |