NeXTs /
Jets.js
| 1 | /*! Jets.js - v0.14.1 - 2018-06-22 |
||
| 2 | * http://NeXTs.github.com/Jets.js/ |
||
| 3 | * Copyright (c) 2015 Denis Lukov; Licensed MIT */ |
||
| 4 | |||
| 5 | ;(function(root, definition) { |
||
| 6 | if (typeof module != 'undefined') module.exports = definition(); |
||
| 7 | else if (typeof define == 'function' && typeof define.amd == 'object') define(definition); |
||
|
0 ignored issues
–
show
|
|||
| 8 | else root['Jets'] = definition(); |
||
| 9 | }(this, function() { |
||
| 10 | "use strict" |
||
| 11 | |||
| 12 | function Jets(opts) { |
||
| 13 | if( ! (this instanceof Jets)) { |
||
| 14 | return new Jets(opts); |
||
| 15 | } |
||
| 16 | var self = this; |
||
| 17 | |||
| 18 | var defaults = { |
||
| 19 | searchSelector: '*AND', |
||
| 20 | hideBy: 'display:none', |
||
| 21 | diacriticsMap: {} |
||
| 22 | } |
||
| 23 | |||
| 24 | self.options = {}; |
||
| 25 | ['columns', 'addImportant', 'searchSelector', 'hideBy', 'manualContentHandling', 'callSearchManually', 'searchInSpecificColumn', 'diacriticsMap', 'didSearch', 'invert'].forEach(function(name) { |
||
| 26 | self.options[name] = opts[name] || defaults[name]; |
||
| 27 | }); |
||
| 28 | if(this.options.searchSelector.length > 1) { |
||
| 29 | var searchSelector = self.options['searchSelector'].trim(); |
||
| 30 | self.options.searchSelector = searchSelector.substr(0, 1); |
||
| 31 | self.options.searchSelectorMode = searchSelector.substr(1).toUpperCase(); |
||
| 32 | } |
||
| 33 | |||
| 34 | self.content_tag = document.querySelectorAll(opts.contentTag); |
||
| 35 | if( ! self.content_tag) throw new Error('Error! Could not find contentTag element'); |
||
| 36 | self.content_param = opts.contentTag; |
||
| 37 | self.search_tag = document.querySelector(opts.searchTag); |
||
| 38 | if( ! self.search_tag && ! self.options.callSearchManually) throw new Error('Error! Provide one of search methods: searchTag or callSearchManually and call .search("phrase") manually'); |
||
| 39 | |||
| 40 | var last_search_query = self.search_tag && self.search_tag.value || ''; |
||
| 41 | self.search = function(search_query, optional_column) { |
||
| 42 | var new_search_query = self.options.callSearchManually && typeof search_query != 'undefined' |
||
| 43 | ? search_query |
||
| 44 | : self.search_tag |
||
| 45 | ? self.search_tag.value |
||
| 46 | : '' |
||
| 47 | if(last_search_query == (last_search_query = new_search_query)) return; |
||
| 48 | (0,self._applyCSS(last_search_query, optional_column)); |
||
| 49 | self.options.didSearch && self.options.didSearch(last_search_query); |
||
| 50 | }; |
||
| 51 | self._onSearch = function(event) { |
||
| 52 | if(event.type == 'keydown') |
||
| 53 | return setTimeout(self.search, 0); |
||
| 54 | self.search(); |
||
| 55 | }; |
||
| 56 | self.destroy = function() { |
||
| 57 | if( ! self.options.callSearchManually) self._processEventListeners('remove'); |
||
| 58 | self._destroy(); |
||
| 59 | }; |
||
| 60 | |||
| 61 | if( ! self.options.callSearchManually) self._processEventListeners('add'); |
||
| 62 | self._addStyleTag(); |
||
| 63 | self._setJets(); |
||
| 64 | self._applyCSS(last_search_query); |
||
| 65 | } |
||
| 66 | |||
| 67 | Jets.prototype = { |
||
| 68 | constructor: Jets, |
||
| 69 | _processEventListeners: function(action) { |
||
| 70 | ['input', 'keydown', 'change'].forEach(function(event_type) { |
||
| 71 | this.search_tag[action + 'EventListener'](event_type, this._onSearch); |
||
| 72 | }.bind(this)); |
||
| 73 | }, |
||
| 74 | _applyCSS: function(search_query, optional_column) { |
||
| 75 | var options = this.options, |
||
| 76 | search_phrase = this.replaceDiacritics(search_query.trim().toLowerCase().replace(/\s\s+/g, ' ')).replace(/\\/g, '\\\\'), |
||
| 77 | words = options.searchSelectorMode |
||
| 78 | ? search_phrase.split(' ').filter(function(item, pos, arr) { return arr.indexOf(item) == pos; }) |
||
| 79 | : [search_phrase], |
||
| 80 | is_strict_selector = options.searchSelectorMode == 'AND', |
||
| 81 | selectors = new Array(words.length); |
||
| 82 | for(var i = 0, ii = words.length; i < ii; i++) { |
||
| 83 | selectors[i] = (is_strict_selector ? this.content_param + '>' : '') + |
||
| 84 | (options.invert ? '' : ':not(') + |
||
| 85 | '[data-jets' + (typeof optional_column != 'undefined' ? '-col-' + optional_column : '') + options.searchSelector + '="' + words[i] + '"]' + |
||
| 86 | (options.invert ? '' : ')'); |
||
| 87 | } |
||
| 88 | var hide_rules = options.hideBy.split(';').filter(Boolean).map(function(rule) { return rule + (options.addImportant ? '!important' : '') }); |
||
| 89 | var css_rule = (is_strict_selector ? '' : this.content_param + '>') + selectors.join(is_strict_selector ? ',' : '') + '{' + hide_rules.join(';') + '}'; |
||
| 90 | this.styleTag.innerHTML = search_phrase.length ? css_rule : ''; |
||
| 91 | }, |
||
| 92 | _addStyleTag: function() { |
||
| 93 | this.styleTag = document.createElement('style'); |
||
| 94 | document.head.appendChild(this.styleTag); |
||
| 95 | }, |
||
| 96 | _getText: function(tag) { |
||
| 97 | return tag && (tag.textContent || tag.innerText) || ''; |
||
| 98 | }, |
||
| 99 | _sanitize: function(text) { |
||
| 100 | return this.replaceDiacritics(text).trim().replace(/\s+/g, ' ').toLowerCase() |
||
| 101 | }, |
||
| 102 | _getContentTags: function(query) { |
||
| 103 | return Array.prototype.slice.call(this.content_tag).reduce(function(all, elem) { |
||
| 104 | return all.concat(Array.prototype.slice.call(elem.querySelectorAll(query || ':scope > *'))); |
||
| 105 | }, []); |
||
| 106 | }, |
||
| 107 | _handleSpecificColumns: function(tag, set) { |
||
| 108 | var self = this; |
||
| 109 | if( ! self.options.searchInSpecificColumn) return; |
||
| 110 | Array.prototype.slice.call(tag.children).map(function(children, i) { |
||
| 111 | if(self.options.columns && self.options.columns.length && self.options.columns.indexOf(i) == -1) return |
||
| 112 | tag[(set || 'remove') + 'Attribute']('data-jets-col-' + i, set && self._sanitize(self._getText(children))); |
||
| 113 | }) |
||
| 114 | }, |
||
| 115 | _setJets: function(query, force) { |
||
| 116 | var self = this, |
||
| 117 | tags = self._getContentTags(force ? '' : query), text; |
||
| 118 | for(var i = 0, tag; tag = tags[i]; i++) { |
||
| 119 | if(tag.hasAttribute('data-jets') && ! force) continue; |
||
| 120 | text = this.options.manualContentHandling |
||
| 121 | ? this.options.manualContentHandling(tag) |
||
| 122 | : self.options.columns && self.options.columns.length |
||
| 123 | ? self.options.columns.map(function(column) { |
||
| 124 | return self._getText(tag.children[column]); |
||
|
0 ignored issues
–
show
|
|||
| 125 | }).join(' ') |
||
| 126 | : self._getText(tag); |
||
| 127 | tag.setAttribute('data-jets', self._sanitize(text)); |
||
| 128 | self._handleSpecificColumns(tag, 'set'); |
||
| 129 | }; |
||
| 130 | }, |
||
| 131 | replaceDiacritics: function(text) { |
||
| 132 | var diacritics = this.options.diacriticsMap; |
||
| 133 | for(var letter in diacritics) if(diacritics.hasOwnProperty(letter)) { |
||
| 134 | for(var i = 0, ii = diacritics[letter].length; i < ii; i++) { |
||
| 135 | text = text.replace(new RegExp(diacritics[letter][i], 'g'), letter); |
||
| 136 | } |
||
| 137 | } |
||
| 138 | return text; |
||
| 139 | }, |
||
| 140 | update: function(force) { |
||
| 141 | this._setJets(':scope > :not([data-jets])', force); |
||
| 142 | }, |
||
| 143 | _destroy: function() { |
||
| 144 | this.styleTag.parentNode && document.head.removeChild(this.styleTag); |
||
| 145 | var tags = this._getContentTags(); |
||
| 146 | for(var i = 0, tag; tag = tags[i]; i++) { |
||
| 147 | tag.removeAttribute('data-jets'); |
||
| 148 | this._handleSpecificColumns(tag); |
||
| 149 | } |
||
| 150 | } |
||
| 151 | } |
||
| 152 | |||
| 153 | // :scope polyfill |
||
| 154 | // http://stackoverflow.com/a/17989803/1221082 |
||
| 155 | ;(function(doc, proto) { |
||
| 156 | try { |
||
| 157 | doc.querySelector(':scope body'); |
||
| 158 | } catch (err) { |
||
| 159 | ['querySelector', 'querySelectorAll'].forEach(function(method) { |
||
| 160 | var nativ = proto[method]; |
||
| 161 | proto[method] = function(selectors) { |
||
| 162 | if (/(^|,)\s*:scope/.test(selectors)) { |
||
| 163 | var id = this.getAttribute('id'); |
||
| 164 | this.id = 'ID_' + Date.now(); |
||
| 165 | selectors = selectors.replace(/((^|,)\s*):scope/g, '$1#' + this.getAttribute('id')); |
||
| 166 | var result = doc[method](selectors); |
||
| 167 | this.id = id; |
||
| 168 | return result; |
||
| 169 | } else { |
||
| 170 | return nativ.call(this, selectors); |
||
| 171 | } |
||
| 172 | } |
||
| 173 | }); |
||
| 174 | } |
||
| 175 | })(window.document, Element.prototype); |
||
|
0 ignored issues
–
show
The variable
Element seems to be never declared. If this is a global, consider adding a /** global: Element */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. Loading history...
|
|||
| 176 | |||
| 177 | return Jets; |
||
| 178 | })); |
||
| 179 |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.