Nội dung bài viết
Video học lập trình mỗi ngày
Autocomplete search là một thuật toán rất phức tạp, và đỏi hòi nhiều thuật toán được áp dụng. Nếu bạn đã từng sử dụng Sublime Text để code thì ở đó bạn để ý rằng, đó là một hệ thống tìm kiếm thông minh, khi chúng ta tìm kiếm một vài ký tự thì hệ thống đã gợi ý cho bạn những từ khoá tìm kiếm cụ thể hơn.
Autocomplete search
Để hình dung hơn thì chúng ta xem một số hình ảnh sau:
Hình 2: Tìm kiếm cfg
Qua hai hình ảnh chúng ta để ý thì khi tìm kiếm cfg thì nó sẽ gợi ý những từ liên quan như config, fold tag, package file. Hoặc chúng ta tìm kiếm java, thì hệ thống đã gợi ý rằng java, javascript, save as, java server page... Vậy làm cách nào để thực hiện chức năng này trên giao diện người dùng? Đây là một ví dụ có thể giúp bạn thực hiện một cách nhanh chóng và chuyên nghiệp hơn.
Example Autocomplete search javascript
Trong code này chủ yếu chúng ta sử dụng "RegExp" javascript. Nếu bạn nào chưa hiểu thì có thể tham khảo thêm về cách học "RegExp javascript".
Trước tiên xem code thì có thể xem DEMO HERE để biết cách hoạt động như thế nào File javascript:
let Searcher = (() => { let escapeRegExp = /[\-#$\^*()+\[\]{}|\\,.?\s]/g; let escapeReg = reg => reg.replace(escapeRegExp, '\\$&'); let groupLeft = '', groupRight = ''; let groupReg = new RegExp(escapeReg(groupRight + groupLeft), 'g'); let groupExtractReg = new RegExp('(' + escapeReg(groupLeft) + '[\\s\\S]+?' + escapeReg(groupRight) + ')', 'g'); let findMax = (str, keyword) => { let max = 0; keyword = groupLeft + keyword + groupRight; str.replace(groupExtractReg, m => { if (keyword == m) { max = Number.MAX_SAFE_INTEGER; } else if (m.length > max) { max = m.length; } }); return max; }; let keyReg = key => { let src = ['(.*?)(']; let ks = key.split(''); if (ks.length) { while (ks.length) { src.push(escapeReg(ks.shift()), ')(.*?)('); } src.pop(); } src.push(')(.*?)'); src = src.join(''); let reg = new RegExp(src, 'i'); let replacer = []; let start = key.length; let begin = 1; while (start > 0) { start--; replacer.push('$', begin, groupLeft + '$', begin + 1, groupRight); begin += 2; } replacer.push('$', begin); info = { regexp: reg, replacement: replacer.join('') }; return info; }; return { search(list, keyword) { let kr = keyReg(keyword); let result = []; for (let e of list) { if (kr.regexp.test(e)) { result.push(e.replace(kr.regexp, kr.replacement) .replace(groupReg, '')); } } result = result.sort((a, b) => findMax(b, keyword) - findMax(a, keyword)); console.log(`result::::`, result) //create div result = result.map(el => { return `${el}` }) return result; } }; })(); // console.log(document.querySelectorAll('.search-prev')); //List demo let list = [ 'javascript', 'es6', 'tipjs ', 'web_development ', 'nodejs ', 'object ', 'webdev ', 'lab-javascript ', 'async-await ', 'array ', 'tips and tricks javascript ', 'mongodb ', 'firebase ', 'promise ', 'auth02 ', 'authenticate token ', 'expressjs', 'token', 'jwt', 'cookie', 'series callback javascript', 'async', 'nginx', 'pattern', 'feature_javascript', 'reduce_javascript', 'build-project', 'exprejs', 'design_pattern', 'session', 'login', 'method', 'css', 'performance', 'jwt and restful api', 'es11', 'mongoose', 'newbie', 'array_javascript', 'data structures and algorithms', 'javascript', 'api', 'secure', 'module', 'rss_code', 'javascript_basic', 'object_assgin', 'spread_operator', 'javascript newbie', 'fireabse_notification', 'interview', 'query_javascript', 'callbacks', 'await', 'destructuring', 'redis', 'scope', 'jsonp', 'moment', 'transaction', 'cors', 'event_loop', 'npm', 'metadata', 'system', 'ebook', 'cluster', 'pm2', 'dom', 'hight-order-function', 'html', 'mysql', 'ffmpeg', 'verify-sms-firebase', 'mysql-nodejs', 'about performance javascript', 'reactjs', 'callback', 'basic', 'ajax', 'reduce', 'middleware', 'iterator', 'series es6 vs react', 'object_javascript', 'es5', 'refreshtoken', 'deep_copy_javascript', 'big-data', 'rss_new', 'http-status-code', 'medium', 'string', 'fetch', 'es12', 'tips_and_tricks', 'console', 'es10', 'cache_js', 'git', 'question', 'puppeteer'] const divCon = document.getElementById('search-items') const input = document.querySelector('input'); input.addEventListener('keypress', (e) => { divCon.innerHTML = ''; const rs = Searcher.search(list, e.target.value); rs.forEach(el => { var div = document.createElement("div"); div.className = 'result'; div.innerHTML = el; divCon.appendChild(div) }) });
File html:
<div class="search-box"> <form no-validade> <input type="text" text="" tabindex="1" class="enter-key" onpropertychange="TextChange(this)" placeholder="Search..." /> </form> <div class="search-prev" id="search-items"> </div> </div>
Có thể xem qua một số hình ảnh sau khi code xong.