aboutsummaryrefslogtreecommitdiffhomepage
path: root/assets
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-11-08 14:07:33 +0100
committerGitHub <noreply@github.com>2020-11-08 14:07:33 +0100
commitd9d71b10c3bc70a0881d630b37dc4e918c9e812f (patch)
treed8f772a9106fbd5072ebee1b9fa536babe90f7b1 /assets
parentc51d65238be43d61b7e6a6f9940948afea0c13fa (diff)
parent8a1ce1da15fdbae99b24700b06f2008c7a657603 (diff)
downloadShaarli-d9d71b10c3bc70a0881d630b37dc4e918c9e812f.tar.gz
Shaarli-d9d71b10c3bc70a0881d630b37dc4e918c9e812f.tar.zst
Shaarli-d9d71b10c3bc70a0881d630b37dc4e918c9e812f.zip
Merge pull request #1621 from ArthurHoaro/feature/tag-separators
Diffstat (limited to 'assets')
-rw-r--r--assets/default/js/base.js29
-rw-r--r--assets/default/scss/shaarli.scss10
-rw-r--r--assets/vintage/js/base.js45
3 files changed, 54 insertions, 30 deletions
diff --git a/assets/default/js/base.js b/assets/default/js/base.js
index 66badfb2..dd532bb7 100644
--- a/assets/default/js/base.js
+++ b/assets/default/js/base.js
@@ -42,19 +42,21 @@ function refreshToken(basePath, callback) {
42 xhr.send(); 42 xhr.send();
43} 43}
44 44
45function createAwesompleteInstance(element, tags = []) { 45function createAwesompleteInstance(element, separator, tags = []) {
46 const awesome = new Awesomplete(Awesomplete.$(element)); 46 const awesome = new Awesomplete(Awesomplete.$(element));
47 // Tags are separated by a space 47
48 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]);
49 // Insert new selected tag in the input 50 // Insert new selected tag in the input
50 awesome.replace = (text) => { 51 awesome.replace = (text) => {
51 const before = awesome.input.value.match(/^.+ \s*|/)[0]; 52 const before = awesome.input.value.match(new RegExp(`^.+${separator}+|`))[0];
52 awesome.input.value = `${before}${text} `; 53 awesome.input.value = `${before}${text}${separator}`;
53 }; 54 };
54 // Highlight found items 55 // Highlight found items
55 awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(/[^ ]*$/)[0]); 56 awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(new RegExp(`[^${separator}]*$`))[0]);
56 // Don't display already selected items 57 // Don't display already selected items
57 const reg = /(\w+) /g; 58 // WARNING: pseudo classes does not seem to work with string litterals...
59 const reg = new RegExp(`([^${separator}]+)${separator}`, 'g');
58 let match; 60 let match;
59 awesome.data = (item, input) => { 61 awesome.data = (item, input) => {
60 while ((match = reg.exec(input))) { 62 while ((match = reg.exec(input))) {
@@ -78,13 +80,14 @@ function createAwesompleteInstance(element, tags = []) {
78 * @param selector CSS selector 80 * @param selector CSS selector
79 * @param tags Array of tags 81 * @param tags Array of tags
80 * @param instances List of existing awesomplete instances 82 * @param instances List of existing awesomplete instances
83 * @param separator Tags separator character
81 */ 84 */
82function updateAwesompleteList(selector, tags, instances) { 85function updateAwesompleteList(selector, tags, instances, separator) {
83 if (instances.length === 0) { 86 if (instances.length === 0) {
84 // First load: create Awesomplete instances 87 // First load: create Awesomplete instances
85 const elements = document.querySelectorAll(selector); 88 const elements = document.querySelectorAll(selector);
86 [...elements].forEach((element) => { 89 [...elements].forEach((element) => {
87 instances.push(createAwesompleteInstance(element, tags)); 90 instances.push(createAwesompleteInstance(element, separator, tags));
88 }); 91 });
89 } else { 92 } else {
90 // Update awesomplete tag list 93 // Update awesomplete tag list
@@ -214,6 +217,8 @@ function init(description) {
214 217
215(() => { 218(() => {
216 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 || ' ' : ' ';
217 222
218 /** 223 /**
219 * Handle responsive menu. 224 * Handle responsive menu.
@@ -575,7 +580,7 @@ function init(description) {
575 580
576 // Refresh awesomplete values 581 // Refresh awesomplete values
577 existingTags = existingTags.map((tag) => (tag === fromtag ? totag : tag)); 582 existingTags = existingTags.map((tag) => (tag === fromtag ? totag : tag));
578 awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes); 583 awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes, tagsSeparator);
579 } 584 }
580 }; 585 };
581 xhr.send(`renametag=1&fromtag=${fromtagUrl}&totag=${encodeURIComponent(totag)}&token=${refreshedToken}`); 586 xhr.send(`renametag=1&fromtag=${fromtagUrl}&totag=${encodeURIComponent(totag)}&token=${refreshedToken}`);
@@ -615,14 +620,14 @@ function init(description) {
615 refreshToken(basePath); 620 refreshToken(basePath);
616 621
617 existingTags = existingTags.filter((tagItem) => tagItem !== tag); 622 existingTags = existingTags.filter((tagItem) => tagItem !== tag);
618 awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes); 623 awesomepletes = updateAwesompleteList('.rename-tag-input', existingTags, awesomepletes, tagsSeparator);
619 } 624 }
620 }); 625 });
621 }); 626 });
622 627
623 const autocompleteFields = document.querySelectorAll('input[data-multiple]'); 628 const autocompleteFields = document.querySelectorAll('input[data-multiple]');
624 [...autocompleteFields].forEach((autocompleteField) => { 629 [...autocompleteFields].forEach((autocompleteField) => {
625 awesomepletes.push(createAwesompleteInstance(autocompleteField)); 630 awesomepletes.push(createAwesompleteInstance(autocompleteField, tagsSeparator));
626 }); 631 });
627 632
628 const exportForm = document.querySelector('#exportform'); 633 const exportForm = document.querySelector('#exportform');
diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss
index 3404ce12..cc8ccc1e 100644
--- a/assets/default/scss/shaarli.scss
+++ b/assets/default/scss/shaarli.scss
@@ -139,6 +139,16 @@ body,
139 } 139 }
140} 140}
141 141
142.page-form,
143.pure-alert {
144 code {
145 display: inline-block;
146 padding: 0 2px;
147 color: $dark-grey;
148 background-color: var(--background-color);
149 }
150}
151
142// Make pure-extras alert closable. 152// Make pure-extras alert closable.
143.pure-alert-closable { 153.pure-alert-closable {
144 .fa-times { 154 .fa-times {
diff --git a/assets/vintage/js/base.js b/assets/vintage/js/base.js
index 66830b59..55f1c37d 100644
--- a/assets/vintage/js/base.js
+++ b/assets/vintage/js/base.js
@@ -2,29 +2,38 @@ import Awesomplete from 'awesomplete';
2import 'awesomplete/awesomplete.css'; 2import 'awesomplete/awesomplete.css';
3 3
4(() => { 4(() => {
5 const awp = Awesomplete.$;
6 const autocompleteFields = document.querySelectorAll('input[data-multiple]'); 5 const autocompleteFields = document.querySelectorAll('input[data-multiple]');
6 const tagsSeparatorElement = document.querySelector('input[name="tags_separator"]');
7 const tagsSeparator = tagsSeparatorElement ? tagsSeparatorElement.value || ' ' : ' ';
8
7 [...autocompleteFields].forEach((autocompleteField) => { 9 [...autocompleteFields].forEach((autocompleteField) => {
8 const awesomplete = new Awesomplete(awp(autocompleteField)); 10 const awesome = new Awesomplete(Awesomplete.$(autocompleteField));
9 awesomplete.filter = (text, input) => Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]); 11
10 awesomplete.replace = (text) => { 12 // Tags are separated by separator
11 const before = awesomplete.input.value.match(/^.+ \s*|/)[0]; 13 awesome.filter = (text, input) => Awesomplete.FILTER_CONTAINS(
12 awesomplete.input.value = `${before}${text} `; 14 text,
15 input.match(new RegExp(`[^${tagsSeparator}]*$`))[0],
16 );
17 // Insert new selected tag in the input
18 awesome.replace = (text) => {
19 const before = awesome.input.value.match(new RegExp(`^.+${tagsSeparator}+|`))[0];
20 awesome.input.value = `${before}${text}${tagsSeparator}`;
13 }; 21 };
14 awesomplete.minChars = 1; 22 // Highlight found items
23 awesome.item = (text, input) => Awesomplete.ITEM(text, input.match(new RegExp(`[^${tagsSeparator}]*$`))[0]);
15 24
16 autocompleteField.addEventListener('input', () => { 25 // Don't display already selected items
17 const proposedTags = autocompleteField.getAttribute('data-list').replace(/,/g, '').split(' '); 26 // WARNING: pseudo classes does not seem to work with string litterals...
18 const reg = /(\w+) /g; 27 const reg = new RegExp(`([^${tagsSeparator}]+)${tagsSeparator}`, 'g');
19 let match; 28 let match;
20 while ((match = reg.exec(autocompleteField.value)) !== null) { 29 awesome.data = (item, input) => {
21 const id = proposedTags.indexOf(match[1]); 30 while ((match = reg.exec(input))) {
22 if (id !== -1) { 31 if (item === match[1]) {
23 proposedTags.splice(id, 1); 32 return '';
24 } 33 }
25 } 34 }
26 35 return item;
27 awesomplete.list = proposedTags; 36 };
28 }); 37 awesome.minChars = 1;
29 }); 38 });
30})(); 39})();