]> BookStack Code Mirror - bookstack/blob - resources/assets/js/vues/search.js
Update search.js
[bookstack] / resources / assets / js / vues / search.js
1 const moment = require('moment');
2
3 let data = {
4     terms: '',
5     termString : '',
6     search: {
7         type: {
8             page: true,
9             chapter: true,
10             book: true
11         },
12         exactTerms: [],
13         tagTerms: [],
14         option: {},
15         dates: {
16             updated_after: false,
17             updated_before: false,
18             created_after: false,
19             created_before: false,
20         }
21     }
22 };
23
24 let computed = {
25
26 };
27
28 let methods = {
29
30     appendTerm(term) {
31         this.termString += ' ' + term;
32         this.termString = this.termString.replace(/\s{2,}/g, ' ');
33         this.termString = this.termString.replace(/^\s+/, '');
34         this.termString = this.termString.replace(/\s+$/, '');
35     },
36
37     exactParse(searchString) {
38         this.search.exactTerms = [];
39         let exactFilter = /"(.+?)"/g;
40         let matches;
41         while ((matches = exactFilter.exec(searchString)) !== null) {
42             this.search.exactTerms.push(matches[1]);
43         }
44     },
45
46     exactChange() {
47         let exactFilter = /"(.+?)"/g;
48         this.termString = this.termString.replace(exactFilter, '');
49         let matchesTerm = this.search.exactTerms.filter(term => {
50             return term.trim() !== '';
51         }).map(term => {
52             return `"${term}"`
53         }).join(' ');
54         this.appendTerm(matchesTerm);
55     },
56
57     addExact() {
58         this.search.exactTerms.push('');
59         setTimeout(() => {
60             let exactInputs = document.querySelectorAll('.exact-input');
61             exactInputs[exactInputs.length - 1].focus();
62         }, 100);
63     },
64
65     removeExact(index) {
66         this.search.exactTerms.splice(index, 1);
67         this.exactChange();
68     },
69
70     tagParse(searchString) {
71         this.search.tagTerms = [];
72         let tagFilter = /\[(.+?)\]/g;
73         let matches;
74         while ((matches = tagFilter.exec(searchString)) !== null) {
75             this.search.tagTerms.push(matches[1]);
76         }
77     },
78
79     tagChange() {
80         let tagFilter = /\[(.+?)\]/g;
81         this.termString = this.termString.replace(tagFilter, '');
82         let matchesTerm = this.search.tagTerms.filter(term => {
83             return term.trim() !== '';
84         }).map(term => {
85             return `[${term}]`
86         }).join(' ');
87         this.appendTerm(matchesTerm);
88     },
89
90     addTag() {
91         this.search.tagTerms.push('');
92         setTimeout(() => {
93             let tagInputs = document.querySelectorAll('.tag-input');
94             tagInputs[tagInputs.length - 1].focus();
95         }, 100);
96     },
97
98     removeTag(index) {
99         this.search.tagTerms.splice(index, 1);
100         this.tagChange();
101     },
102
103     typeParse(searchString) {
104         let typeFilter = /{\s?type:\s?(.*?)\s?}/;
105         let match = searchString.match(typeFilter);
106         let type = this.search.type;
107         if (!match) {
108             type.page = type.book = type.chapter = true;
109             return;
110         }
111         let splitTypes = match[1].replace(/ /g, '').split('|');
112         type.page = (splitTypes.indexOf('page') !== -1);
113         type.chapter = (splitTypes.indexOf('chapter') !== -1);
114         type.book = (splitTypes.indexOf('book') !== -1);
115     },
116
117     typeChange() {
118         let typeFilter = /{\s?type:\s?(.*?)\s?}/;
119         let type = this.search.type;
120         if (type.page === type.chapter && type.page === type.book) {
121             this.termString = this.termString.replace(typeFilter, '');
122             return;
123         }
124         let selectedTypes = Object.keys(type).filter(type => {return this.search.type[type];}).join('|');
125         let typeTerm = '{type:'+selectedTypes+'}';
126         if (this.termString.match(typeFilter)) {
127             this.termString = this.termString.replace(typeFilter, typeTerm);
128             return;
129         }
130         this.appendTerm(typeTerm);
131     },
132
133     optionParse(searchString) {
134         let optionFilter = /{([a-z_\-:]+?)}/gi;
135         let matches;
136         while ((matches = optionFilter.exec(searchString)) !== null) {
137             this.search.option[matches[1].toLowerCase()] = true;
138         }
139     },
140
141     optionChange(optionName) {
142         let isChecked = this.search.option[optionName];
143         if (isChecked) {
144             this.appendTerm(`{${optionName}}`);
145         } else {
146             this.termString = this.termString.replace(`{${optionName}}`, '');
147         }
148     },
149
150     updateSearch(e) {
151         e.preventDefault();
152         window.location = window.baseUrl('/search?term=' + encodeURIComponent(this.termString));
153     },
154
155     enableDate(optionName) {
156         this.search.dates[optionName.toLowerCase()] = moment().format('YYYY-MM-DD');
157         this.dateChange(optionName);
158     },
159
160     dateParse(searchString) {
161         let dateFilter = /{([a-z_\-]+?):([a-z_\-0-9]+?)}/gi;
162         let dateTags = Object.keys(this.search.dates);
163         let matches;
164         while ((matches = dateFilter.exec(searchString)) !== null) {
165             if (dateTags.indexOf(matches[1]) === -1) continue;
166             this.search.dates[matches[1].toLowerCase()] = matches[2];
167         }
168     },
169
170     dateChange(optionName) {
171         let dateFilter = new RegExp('{\\s?'+optionName+'\\s?:([a-z_\\-0-9]+?)}', 'gi');
172         this.termString = this.termString.replace(dateFilter, '');
173         if (!this.search.dates[optionName]) return;
174         this.appendTerm(`{${optionName}:${this.search.dates[optionName]}}`);
175     },
176
177     dateRemove(optionName) {
178         this.search.dates[optionName] = false;
179         this.dateChange(optionName);
180     }
181
182 };
183
184 function created() {
185     this.termString = document.querySelector('[name=searchTerm]').value;
186     this.typeParse(this.termString);
187     this.exactParse(this.termString);
188     this.tagParse(this.termString);
189     this.optionParse(this.termString);
190     this.dateParse(this.termString);
191 }
192
193 module.exports = {
194     data, computed, methods, created
195 };