diff --git a/src/index.html b/src/index.html index f6f5f21..9352097 100644 --- a/src/index.html +++ b/src/index.html @@ -405,6 +405,7 @@ + diff --git a/src/script.js b/src/script.js index 92b84cc..e3560fd 100644 --- a/src/script.js +++ b/src/script.js @@ -1011,8 +1011,6 @@ settingsBtn, onboardModal, notificationsBtn, onboardShowInTabOptionBtn, onboardD }, 350); toggleSavedItemsPane(); } - - utils.log(event.keyCode) }); window.addEventListener('click', function(e) { @@ -1049,8 +1047,11 @@ settingsBtn, onboardModal, notificationsBtn, onboardShowInTabOptionBtn, onboardD trackEvent('ui', 'addLibrarySelect', target.selectedOptions[0].label); onExternalLibChange(); }); - externalJsTextarea.addEventListener('change', onExternalLibChange); - externalCssTextarea.addEventListener('change', onExternalLibChange); + externalJsTextarea.addEventListener('blur', onExternalLibChange); + externalCssTextarea.addEventListener('blur', onExternalLibChange); + + new TextareaAutoComplete(externalJsTextarea, obj => obj.latest.match(/\.js$/)); + new TextareaAutoComplete(externalCssTextarea, obj => obj.latest.match(/\.css$/)); chrome.storage.local.get({ layoutMode: 1, diff --git a/src/style.css b/src/style.css index 6a0a702..2f53c58 100644 --- a/src/style.css +++ b/src/style.css @@ -582,6 +582,7 @@ li.CodeMirror-hint-active { color: #333; cursor: pointer; } +.dropdown__menu > li.selected > a, .dropdown__menu > li > a:hover { background: var(--color-sidebar); color: white; @@ -678,3 +679,10 @@ li.CodeMirror-hint-active { background: white url('data:image/svg+xml;charset=UTF-8,'); } +.autocomplete-dropdown { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + right: 0; + max-height: 200px; + overflow-y: auto; +} \ No newline at end of file diff --git a/src/textarea-autocomplete.js b/src/textarea-autocomplete.js new file mode 100644 index 0000000..3dc289b --- /dev/null +++ b/src/textarea-autocomplete.js @@ -0,0 +1,119 @@ +// textarea-autocomplete.js +(function() { + + var timeout; + var t, list; + var isShowingSuggestions = false; + + class TextareaAutoComplete { + + constructor (textarea, filter) { + this.t = textarea; + this.filter = filter; + var wrap = document.createElement('div'); + wrap.classList.add('btn-group'); + textarea.parentElement.insertBefore(wrap, textarea); + wrap.insertBefore(textarea, null); + this.list = document.createElement('ul'); + this.list.classList.add('dropdown__menu'); + this.list.classList.add('autocomplete-dropdown'); + wrap.insertBefore(this.list, null); + + this.t.addEventListener('input', e => this.onInput(e)); + this.t.addEventListener('keydown', e => this.onKeyDown(e)); + this.t.addEventListener('blur', e => this.closeSuggestions()) + } + + get currentLineNumber() { + return this.t.value.substr(0, this.t.selectionStart).split('\n').length; + } + get currentLine() { + var line = this.currentLineNumber; + return this.t.value.split('\n')[line - 1]; + } + closeSuggestions() { + this.list.parentElement.classList.remove('open'); + this.isShowingSuggestions = false; + } + getList(input) { + // return new Promise((resolve) => { + // resolve([ + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // { name: 'asdsd', latest: 'dsfdsfsdf/sdf/sd/f/df'}, + // ]) + // }) + var url = 'https://api.cdnjs.com/libraries?search='; + return fetch(url + input) + .then(response => { + return response.json().then(json => json.results); + }); + } + replaceCurrentLine(val) { + var lines = this.t.value.split('\n'); + lines.splice(this.currentLineNumber - 1, 1, val) + this.t.value = lines.join('\n'); + } + onInput() { + var currentLine = this.currentLine; + if (currentLine) { + clearTimeout(this.timeout); + this.timeout = setTimeout(() => { + this.getList(currentLine).then(arr => { + if (!arr.length) { + this.closeSuggestions(); + return; + } + this.list.innerHTML = ''; + if (this.filter) { + arr = arr.filter(this.filter); + } + for (var i = 0; i < Math.min(arr.length, 10); i++) { + this.list.innerHTML += `
  • ${arr[i].name}
  • `; + } + this.list.parentElement.classList.add('open'); + this.isShowingSuggestions = true; + }); + }, 500); + } + } + onKeyDown(event) { + if (event.keyCode === 27) { + this.closeSuggestions(); + event.stopPropagation(); + } + if (event.keyCode === 40 && this.isShowingSuggestions) { + var selectedItemElement = this.list.querySelector('.selected'); + if (selectedItemElement) { + selectedItemElement.classList.remove('selected'); + selectedItemElement.nextElementSibling.classList.add('selected'); + } else { + this.list.querySelector('li:first-child').classList.add('selected'); + } + event.preventDefault(); + } else if (event.keyCode === 38 && this.isShowingSuggestions) { + var selectedItemElement = this.list.querySelector('.selected'); + if (selectedItemElement) { + selectedItemElement.classList.remove('selected'); + selectedItemElement.previousElementSibling.classList.add('selected'); + } else { + this.list.querySelector('li:first-child').classList.add('selected'); + } + event.preventDefault(); + } else if (event.keyCode === 13 && this.isShowingSuggestions) { + var selectedItemElement = this.list.querySelector('.selected'); + this.replaceCurrentLine(selectedItemElement.dataset.url) + this.closeSuggestions(); + } + } + } + + window.TextareaAutoComplete = TextareaAutoComplete; + +})(); \ No newline at end of file