From 380d9d92d104945648c1ad9daf98fd2d55861e0a Mon Sep 17 00:00:00 2001 From: Cade Scroggins Date: Tue, 9 Oct 2018 12:15:49 -0700 Subject: [PATCH] small changes + fix from #18 --- README.md | 28 ++++++--- index.html | 180 +++++++++++++++++++++++------------------------------ 2 files changed, 95 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index f09c3f0..2eb377e 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Inspired by [/r/startpages](https://www.reddit.com/r/startpages)—the idea is t To go to a site, enter the corresponding key. To view the available sites and their keys, press `?`. If your input doesn't match any of the commands, a generic Google search will be triggered. For example: -* Entering `r` would redirect you to [www.reddit.com](https://www.reddit.com). -* Entering `t` would redirect you to [twitch.tv](https://www.twitch.tv). -* Entering `cats` would search [Google for cats](https://encrypted.google.com/search?q=cats). +- Entering `r` would redirect you to [www.reddit.com](https://www.reddit.com). +- Entering `t` would redirect you to [twitch.tv](https://www.twitch.tv). +- Entering `cats` would search [Google for cats](https://encrypted.google.com/search?q=cats). On mobile, you can click the clock to focus the search input. @@ -18,26 +18,34 @@ On mobile, you can click the clock to focus the search input. You can search any of the sites by typing a colon after the site's key, followed by your search query. For example: -* Entering `g:tilde` would search [GitHub for tilde](https://github.com/search?q=tilde). -* Entering `s:radiohead` would search [SoundCloud for radiohead](https://soundcloud.com/search?q=radiohead). +- Entering `g:tilde` would search [GitHub for tilde](https://github.com/search?q=tilde). +- Entering `s:radiohead` would search [SoundCloud for radiohead](https://soundcloud.com/search?q=radiohead). ### Specific Locations You can go to a specific location on a site by typing a forward slash after the site's key, followed by the location on the site you'd like to be redirected to. For example: -* Entering `r/r/startpages` would redirect you to [www.reddit.com/r/startpages](https://www.reddit.com/r/startpages) -* Entering `h/popular` would redirect you to [hypem.com/popular](http://hypem.com/popular). +- Entering `r/r/startpages` would redirect you to [www.reddit.com/r/startpages](https://www.reddit.com/r/startpages) +- Entering `h/popular` would redirect you to [hypem.com/popular](http://hypem.com/popular). ### URL Redirects If you enter in a full domain or URL, you will be redirected to said domain or URL. For example: -* Entering `stallman.org` would redirect you to [stallman.org](https://stallman.org/). -* Entering `https://smile.amazon.com` would redirect you to [smile.amazon.com](https://smile.amazon.com/). +- Entering `stallman.org` would redirect you to [stallman.org](https://stallman.org/). +- Entering `https://smile.amazon.com` would redirect you to [smile.amazon.com](https://smile.amazon.com/). + +### Query Paramater + +Additionally, you can pass any query via the `q` query param. For example: + +- Going to `file:///path/to/tilde/index.html?q=cats` would search [Google for cats](https://encrypted.google.com/search?q=cats). + +This allows you to invoke Tilde with your native browser search bar. ## Configuration -The above is just the beginning. Open up the [index.html](index.html) file and read through the `CONFIG`! +The above is _just the beginning_. Open up the [index.html](index.html) file and read through the `CONFIG`! ## License diff --git a/index.html b/index.html index e8d5434..7e5b915 100644 --- a/index.html +++ b/index.html @@ -83,14 +83,10 @@ pathDelimiter: '/', // the delimiter between the hours and minutes in the clock - clockDelimiter: ' ', + clockDelimiter: ' ', // change clock to twelve hour format twelveHour: false, - - // note: you can pass in your search query via the q query param - // e.g. going to file:///path/to/tilde/index.html?q=hamsters is equivalent - // to typing "hamsters" and pressing enter }; @@ -220,12 +216,12 @@ .search-suggestion b::after { content: ' '; position: absolute; - top: 51%; right: 0; + bottom: -.4em; left: 0; height: 3px; background-color: var(--color0); - opacity: .8; + opacity: .3; } .search-suggestion.highlight b::after { @@ -374,7 +370,7 @@
- +
    @@ -420,6 +416,8 @@ case 91: return 'super'; } }, + + pad: v => ('0' + v.toString()).slice(-2), }; class Clock { @@ -429,21 +427,13 @@ this._form = options.form; this._twelveHour = options.twelveHour; this._setTime = this._setTime.bind(this); - this._registerEvents(); - this._start(); - } - - _pad(num) { - return ('0' + num.toString()).slice(-2); - } - - _registerEvents() { this._el.addEventListener('click', this._form.show); + this._start(); } _setTime() { const date = new Date(); - let hours = this._pad(date.getHours()); + let hours = $.pad(date.getHours()); let amPm = ''; if (this._twelveHour) { @@ -457,7 +447,7 @@ `${date.getHours() > 12 ? 'PM' : 'AM'}`; } - const minutes = this._pad(date.getMinutes()); + const minutes = $.pad(date.getMinutes()); this._el.innerHTML = `${hours}${this._delimiter}${minutes}${amPm}`; this._el.setAttribute('datetime', date.toTimeString()); } @@ -474,8 +464,8 @@ this._commands = options.commands; this._newTab = options.newTab; this._toggled = false; + this._handleKeydown = this._handleKeydown.bind(this); this._buildAndAppendLists(); - this._bindMethods(); this._registerEvents(); } @@ -484,10 +474,6 @@ this._toggled ? $.bodyClassAdd('help') : $.bodyClassRemove('help'); } - _bindMethods() { - this._handleKeydown = this._handleKeydown.bind(this); - } - _buildAndAppendLists() { const lists = document.createElement('ul'); lists.classList.add('categories'); @@ -506,18 +492,20 @@ } _buildListCommands(category) { - return this._commands.map(([cmdCategory, name, key, url]) => { - if (cmdCategory === category) { - return ( - `
  • - - ${key} - ${name} - -
  • ` - ); - } - }).join(''); + return this._commands + .map(([cmdCategory, name, key, url]) => { + if (cmdCategory === category) { + return ( + `
  • + + ${key} + ${name} + +
  • ` + ); + } + }) + .join(''); } _getCategories() { @@ -544,7 +532,6 @@ } addItem() {} - getSuggestions() {} _addSearchPrefix(items, query) { @@ -619,14 +606,19 @@ }); if (!exists) history.push([query, 1]); - this._setHistory(this._sort(history)); + + const sorted = history + .sort((current, next) => current[1] - next[1]) + .reverse(); + + this._setHistory(sorted); } getSuggestions(query) { return new Promise(resolve => { const suggestions = this._getHistory() .map(([item]) => item) - .filter(item => this._itemContainsQuery(query, item)) + .filter(item => query && !$.ieq(item, query) && $.iin(item, query)) .slice(0, this._limit); resolve(suggestions); @@ -642,10 +634,6 @@ return this._history; } - _itemContainsQuery(query, item) { - return query && !$.ieq(item, query) && $.iin(item, query); - } - _save(history) { localStorage.setItem(this._storeName, JSON.stringify(history)); } @@ -654,10 +642,6 @@ this._history = history; this._save(history); } - - _sort(history) { - return history.sort((current, next) => current[1] - next[1]).reverse(); - } } class Suggester { @@ -666,7 +650,7 @@ this._influencers = options.influencers; this._limit = options.limit; this._suggestionEls = []; - this._bindMethods(); + this._handleKeydown = this._handleKeydown.bind(this); this._registerEvents(); } @@ -692,8 +676,9 @@ if (input === '') this._clearSuggestions(); Promise.all(this._getInfluencerPromises(input)).then(res => { - const suggestions = this._flattenAndUnique(res); + const suggestions = Suggester._flattenAndUnique(res); this._clearSuggestions(); + if (suggestions.length) { this._appendSuggestions(suggestions, input); this._registerSuggestionEvents(); @@ -702,8 +687,13 @@ }); } + // [[1, 2], [1, 2, 3, 4]] -> [1, 2, 3, 4] + static _flattenAndUnique(array) { + return [...new Set([].concat.apply([], array))]; + } + _appendSuggestions(suggestions, input) { - suggestions.some((suggestion, i) => { + for (const [i, suggestion] of suggestions.entries()) { const match = new RegExp($.escapeRegex(input), 'ig'); const suggestionHtml = suggestion.replace(match, `${input}`); @@ -721,16 +711,12 @@ `, ); - return i + 1 >= this._limit; - }); + if (i + 1 >= this._limit) break; + } this._suggestionEls = $.els('.js-search-suggestion'); } - _bindMethods() { - this._handleKeydown = this._handleKeydown.bind(this); - } - _clearClickEvents() { this._suggestionEls.forEach(el => { const callback = this._onClick.bind(null, el.value); @@ -745,11 +731,6 @@ this._el.innerHTML = ''; } - // [[1, 2], [1, 2, 3, 4]] -> [1, 2, 3, 4] - _flattenAndUnique(array) { - return [...new Set([].concat.apply([], array))]; - } - _focusNext(e) { const exists = this._suggestionEls.some((el, i) => { if (el.classList.contains('highlight')) { @@ -797,12 +778,18 @@ } _registerSuggestionEvents() { - this._suggestionEls.forEach(el => { - const value = el.getAttribute('data-suggestion'); - el.addEventListener('mouseover', this._highlight.bind(this, el)); - el.addEventListener('mouseout', this._unHighlight.bind(this)); - el.addEventListener('click', this._onClick.bind(null, value)); - }); + const noHighlightUntilMouseMove = () => { + window.removeEventListener('mousemove', noHighlightUntilMouseMove); + + this._suggestionEls.forEach(el => { + const value = el.getAttribute('data-suggestion'); + el.addEventListener('mouseover', this._highlight.bind(this, el)); + el.addEventListener('mouseout', this._unHighlight.bind(this)); + el.addEventListener('click', this._onClick.bind(null, value)); + }); + }; + + window.addEventListener('mousemove', noHighlightUntilMouseMove); } _unHighlight(e) { @@ -845,12 +832,12 @@ if (res.isSearch && searchPath) { res.split = this._searchDelimiter; - res.query = this._shiftAndTrim(splitSearch, res.split); - res.redirect = this._prepSearch(url, searchPath, res.query); + res.query = QueryParser._shiftAndTrim(splitSearch, res.split); + res.redirect = QueryParser._prepSearch(url, searchPath, res.query); } else if (res.isPath) { res.split = this._pathDelimiter; - res.path = this._shiftAndTrim(splitPath, res.split); - res.redirect = this._prepPath(url, res.path); + res.path = QueryParser._shiftAndTrim(splitPath, res.split); + res.redirect = QueryParser._prepPath(url, res.path); } else { res.redirect = url; } @@ -859,48 +846,41 @@ } if (key === '*') { - res.redirect = this._prepSearch(url, searchPath, query); + res.redirect = QueryParser._prepSearch(url, searchPath, query); } }); } - res.color = this._getColorFromUrl(res.redirect); + res.color = QueryParser._getColorFromUrl(this._commands, res.redirect); return res; } - _getColorFromUrl(url) { - const domain = this._getHostname(url); - const color = this._commands - .filter(c => this._getHostname(c[3]) === domain) - .map(c => c[5])[0]; + static _getColorFromUrl(commands, url) { + const domain = new URL(url).hostname; - return color || null; + return commands + .filter(c => new URL(c[3]).hostname === domain) + .map(c => c[5])[0] || null; } - _getHostname(url) { - const parser = document.createElement('a'); - parser.href = url; - return parser.hostname.replace(/^www./, ''); + static _prepPath(url, path) { + return QueryParser._stripUrlPath(url) + '/' + path; } - _prepPath(url, path) { - return this._stripUrlPath(url) + '/' + path; - } - - _prepSearch(url, searchPath, query) { + static _prepSearch(url, searchPath, query) { if (!searchPath) return url; - const baseUrl = this._stripUrlPath(url); + const baseUrl = QueryParser._stripUrlPath(url); const urlQuery = encodeURIComponent(query); searchPath = searchPath.replace('{}', urlQuery); return baseUrl + searchPath; } - _shiftAndTrim(arr, delimiter) { + static _shiftAndTrim(arr, delimiter) { arr.shift(); return arr.join(delimiter).trim(); } - _stripUrlPath(url) { + static _stripUrlPath(url) { const parser = document.createElement('a'); parser.href = url; return `${parser.protocol}//${parser.hostname}`; @@ -918,7 +898,12 @@ this._instantRedirect = options.instantRedirect; this._newTab = options.newTab; this._inputElVal = ''; - this._bindMethods(); + this._clearPreview = this._clearPreview.bind(this); + this.show = this.show.bind(this); + this._handleInput = this._handleInput.bind(this); + this._handleKeydown = this._handleKeydown.bind(this); + this._previewValue = this._previewValue.bind(this); + this._submitForm = this._submitForm.bind(this); this._registerEvents(); this._loadQueryParam(); } @@ -934,17 +919,6 @@ this._inputEl.focus(); } - _bindMethods() { - this.hide = this.hide.bind(this); - this.show = this.show.bind(this); - this._clearPreview = this._clearPreview.bind(this); - this._handleKeydown = this._handleKeydown.bind(this); - this._handleInput = this._handleInput.bind(this); - this._previewValue = this._previewValue.bind(this); - this._submitForm = this._submitForm.bind(this); - this._submitWithValue = this._submitWithValue.bind(this); - } - _clearPreview() { this._previewValue(this._inputElVal); this._inputEl.focus();