diff --git a/.flowconfig b/.flowconfig index 1a69bd3..39d0f20 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,4 +1,5 @@ [ignore] +/node_modules/.* [include] diff --git a/js/holmes.js b/js/holmes.js index 64b5fd3..19538a8 100644 --- a/js/holmes.js +++ b/js/holmes.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.holmes=t()}(this,function(){"use strict";function e(t,o){if(!(t instanceof Object&&o instanceof Object))throw new Error("One of both arguments isn't an object.");return Object.keys(t).forEach(function(i){n(o[i])!==n(t[i])&&void 0!==t[i]||(o[i]instanceof Object?e(t[i],o[i]):t[i]=o[i])}),t}function t(e){var t=function(){for(var t=void 0,n=arguments.length,o=Array(n),i=0;is.searchString.length||(s.options.dynamic&&(s.elements=document.querySelectorAll(s.options.find),s.elementsLength=s.elements.length,s.elementsArray=Array.prototype.slice.call(s.elements)),s.options.mark&&(s.regex=new RegExp("("+s.searchString+")(?![^<]*>)","gi")),s.elementsArray.forEach(function(t){t.textContent.toLowerCase().includes(s.searchString)?(s._showElement(t),r&&"function"==typeof s.options.onFound&&s.options.onFound(s.placeholderNode),r=!1,e=!0):s._hideElement(t)}),"function"==typeof s.options.onInput&&s.options.onInput(s.searchString),e||r?r||s.options.placeholder&&s.placeholderNode.classList.add(s.options.class.hidden):(r=!0,s.options.placeholder&&s.placeholderNode.classList.remove(s.options.class.hidden),"function"==typeof s.options.onEmpty&&s.options.onEmpty(s.placeholderNode)))}}return i(t,[{key:"_hideElement",value:function(e){this.options.class.visible&&e.classList.remove(this.options.class.visible),e.classList.contains(this.options.class.hidden)||(e.classList.add(this.options.class.hidden),this.hidden++,"function"==typeof this.options.onHidden&&this.options.onHidden(e)),this.options.hiddenAttr&&e.setAttribute("hidden","true"),this.options.mark&&(e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,""))}},{key:"_showElement",value:function(e){this.options.class.visible&&e.classList.add(this.options.class.visible),e.classList.contains(this.options.class.hidden)&&(e.classList.remove(this.options.class.hidden),this.hidden--,"function"==typeof this.options.onVisible&&this.options.onVisible(e)),this.options.hiddenAttr&&e.removeAttribute("hidden"),this.options.mark&&(e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,""),this.searchString.length&&(e.innerHTML=e.innerHTML.replace(this.regex,"$1")))}},{key:"inputString",value:function(){if(this.input instanceof HTMLInputElement)return this.input.value.toLowerCase();if(this.input.contentEditable)return this.input.textContent.toLowerCase();throw new Error("The Holmes input was no or contenteditable.")}},{key:"setInput",value:function(e){if(this.input instanceof HTMLInputElement)this.input.value=e;else{if(!this.input.contentEditable)throw new Error("The Holmes input was no or contenteditable.");this.input.textContent=e}}},{key:"start",value:function(){var e=this;if(this.running=!0,this.input=document.querySelector(this.options.input),!this.options.find)throw new Error('A find argument is needed. That should be a querySelectorAll for each of the items you want to match individually. You should have something like: \nholmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/holmes.html');if(this.elements=document.querySelectorAll(this.options.find),this.elementsLength=this.elements.length,this.elementsArray=Array.prototype.slice.call(this.elements),this.hidden=0,this.options.placeholder){if(this.placeholderNode=document.createElement("div"),this.placeholderNode.id="holmes-placeholder",this.placeholderNode.classList.add(this.options.class.hidden),this.placeholderNode.innerHTML=this.options.placeholder,!(this.elements[0].parentNode instanceof Element))throw new Error("The Holmes placeholder could't be put; the elements had no parent.");this.elements[0].parentNode.appendChild(this.placeholderNode)}this.options.class.visible&&this.elementsArray.forEach(function(t){t.classList.add(e.options.class.visible)}),this.input.addEventListener("input",this._inputHandler)}},{key:"stop",value:function(){var e=this;return new Promise(function(t,n){try{if(e.input.removeEventListener("input",e._inputHandler),e.options.placeholder){if(!e.placeholderNode.parentNode)throw new Error("The Holmes placeholderNode has no parent.");e.placeholderNode.parentNode.removeChild(e.placeholderNode)}e.options.mark&&e.elementsArray.forEach(function(e){e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,"")}),e.running=!1,t("This instance of Holmes has been stopped.")}catch(e){n(e)}})}},{key:"clear",value:function(){var e=this;this.setInput(""),this.options.class.visible?this.elementsArray.forEach(function(t){t.classList.remove(e.options.class.hidden),t.classList.add(e.options.class.visible)}):this.elementsArray.forEach(function(t){t.classList.remove(e.options.class.hidden)}),this.options.placeholder&&(this.placeholderNode.classList.add(this.options.class.hidden),this.options.class.visible&&this.placeholderNode.classList.remove(this.options.class.visible)),this.hidden=0}},{key:"count",value:function(){return{all:this.elementsLength,hidden:this.hidden,visible:this.elementsLength-this.hidden}}}]),t}(),l=t(r);return l}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.holmes=t()}(this,function(){"use strict";function e(t,o){if(!(t instanceof Object&&o instanceof Object))throw new Error("One of both arguments isn't an object.");return Object.keys(t).forEach(function(i){n(o[i])!==n(t[i])&&void 0!==t[i]||(o[i]instanceof Object?e(t[i],o[i]):t[i]=o[i])}),t}function t(e){var t=function(){for(var t=void 0,n=arguments.length,o=Array(n),i=0;is.searchString.length||(s.options.dynamic&&(s.elements=document.querySelectorAll(s.options.find),s.elementsLength=s.elements.length,s.elementsArray=Array.prototype.slice.call(s.elements)),s.options.mark&&(s._regex=new RegExp("("+s.searchString+")(?![^<]*>)","gi")),s.elementsArray.forEach(function(t){t.textContent.toLowerCase().includes(s.searchString)?(s._showElement(t),r&&"function"==typeof s.options.onFound&&s.options.onFound(s.placeholderNode),r=!1,e=!0):s._hideElement(t)}),"function"==typeof s.options.onInput&&s.options.onInput(s.searchString),e||r?r||s.options.placeholder&&s.placeholderNode.classList.add(s.options.class.hidden):(r=!0,s.options.placeholder&&s.placeholderNode.classList.remove(s.options.class.hidden),"function"==typeof s.options.onEmpty&&s.options.onEmpty(s.placeholderNode)))}}return i(t,[{key:"_hideElement",value:function(e){this.options.class.visible&&e.classList.remove(this.options.class.visible),e.classList.contains(this.options.class.hidden)||(e.classList.add(this.options.class.hidden),this.hidden++,"function"==typeof this.options.onHidden&&this.options.onHidden(e)),this.options.hiddenAttr&&e.setAttribute("hidden","true"),this.options.mark&&(e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,""))}},{key:"_showElement",value:function(e){this.options.class.visible&&e.classList.add(this.options.class.visible),e.classList.contains(this.options.class.hidden)&&(e.classList.remove(this.options.class.hidden),this.hidden--,"function"==typeof this.options.onVisible&&this.options.onVisible(e)),this.options.hiddenAttr&&e.removeAttribute("hidden"),this.options.mark&&(e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,""),this.searchString.length&&(e.innerHTML=e.innerHTML.replace(this._regex,"$1")))}},{key:"inputString",value:function(){if(this.input instanceof HTMLInputElement)return this.input.value.toLowerCase();if(this.input.contentEditable)return this.input.textContent.toLowerCase();throw new Error("The Holmes input was no or contenteditable.")}},{key:"setInput",value:function(e){if(this.input instanceof HTMLInputElement)this.input.value=e;else{if(!this.input.contentEditable)throw new Error("The Holmes input was no or contenteditable.");this.input.textContent=e}}},{key:"start",value:function(){var e=this;if(this.running=!0,this.input=document.querySelector(this.options.input),!this.options.find)throw new Error('A find argument is needed. That should be a querySelectorAll for each of the items you want to match individually. You should have something like: \nnew Holmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/holmes.html');if(this.elements=document.querySelectorAll(this.options.find),this.elementsLength=this.elements.length,this.elementsArray=Array.prototype.slice.call(this.elements),this.hidden=0,this.options.placeholder){if(this.placeholderNode=document.createElement("div"),this.placeholderNode.id="holmes-placeholder",this.placeholderNode.classList.add(this.options.class.hidden),this.placeholderNode.innerHTML=this.options.placeholder,!(this.elements[0].parentNode instanceof Element))throw new Error("The Holmes placeholder could't be put; the elements had no parent.");this.elements[0].parentNode.appendChild(this.placeholderNode)}this.options.class.visible&&this.elementsArray.forEach(function(t){t.classList.add(e.options.class.visible)}),this.input.addEventListener("input",this._inputHandler)}},{key:"stop",value:function(){var e=this;return new Promise(function(t,n){try{if(e.input.removeEventListener("input",e._inputHandler),e.options.placeholder){if(!e.placeholderNode.parentNode)throw new Error("The Holmes placeholderNode has no parent.");e.placeholderNode.parentNode.removeChild(e.placeholderNode)}e.options.mark&&e.elementsArray.forEach(function(e){e.innerHTML=e.innerHTML.replace(/<\/?mark>/g,"")}),e.running=!1,t("This instance of Holmes has been stopped.")}catch(e){n(e)}})}},{key:"clear",value:function(){var e=this;this.setInput(""),this.options.class.visible?this.elementsArray.forEach(function(t){t.classList.remove(e.options.class.hidden),t.classList.add(e.options.class.visible)}):this.elementsArray.forEach(function(t){t.classList.remove(e.options.class.hidden)}),this.options.placeholder&&(this.placeholderNode.classList.add(this.options.class.hidden),this.options.class.visible&&this.placeholderNode.classList.remove(this.options.class.visible)),this.hidden=0}},{key:"count",value:function(){return{all:this.elementsLength,hidden:this.hidden,visible:this.elementsLength-this.hidden}}}]),t}(),l=t(r);return l}); diff --git a/js/main.js b/js/main.js index 7aa555d..89fd91e 100644 --- a/js/main.js +++ b/js/main.js @@ -6,6 +6,36 @@ import {mergeObj, toFactory} from './util.js'; */ class Holmes { + elements: NodeList; + elementsArray: Array; + elementsLength: number; + hidden: number; + input: HTMLElement; + options: { + input: string, + find: string, + placeholder: ?string, + mark: ?boolean, + class: { + visible: ?string, + hidden: string + }, + dynamic: ?boolean, + instant: ?boolean, + minCharacters: ?number, + hiddenAttr: ?boolean, + onHidden: ?function, + onVisible: ?function, + onEmpty: ?function, + onFound: ?function, + onInput: ?function, + }; + running: boolean; + placeholderNode: HTMLElement; + searchString: string; + _regex: RegExp; + _inputHandler: function; + /** * search for dom elements on your page * @@ -78,7 +108,7 @@ class Holmes { */ this.options = { input: 'input[type=search]', - find: undefined, + find: '', placeholder: undefined, mark: false, class: { @@ -115,7 +145,7 @@ class Holmes { * @memberOf holmes * @instance */ - this.input = undefined; + this.input; /** * All of the elements that are searched @@ -124,7 +154,7 @@ class Holmes { * @memberOf holmes * @instance */ - this.elements = undefined; + this.elements; /** * Placeholder element @@ -133,7 +163,16 @@ class Holmes { * @memberOf holmes * @instance */ - this.placeholderNode = undefined; + this.placeholderNode; + + /** + * Is the current instance running + * @member running + * @memberOf holmes + * @instance + * @type {Boolean} + */ + this.running = false; if (this.options.instant) { this.start(options); @@ -371,8 +410,9 @@ class Holmes { // if a visible class is given, give it to everything if (this.options.class.visible) { + const vis: string = this.options.class.visible; this.elementsArray.forEach((element => { - element.classList.add(this.options.class.visible); + element.classList.add(vis); })); } @@ -429,16 +469,17 @@ class Holmes { this.setInput(''); // if a visible class is given, give it to everything if (this.options.class.visible) { + const vis: string = this.options.class.visible; this.elementsArray.forEach(element => { element.classList.remove(this.options.class.hidden); - element.classList.add(this.options.class.visible); + element.classList.add(vis); }); } else { this.elementsArray.forEach(element => { element.classList.remove(this.options.class.hidden); }); } - if (this.options.placeholder) { + if (this.options.placeholder && this.options.class.hidden) { this.placeholderNode.classList.add(this.options.class.hidden); if (this.options.class.visible) { this.placeholderNode.classList.remove(this.options.class.visible); diff --git a/package.json b/package.json index 4fa8ff9..1e621f8 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "jsdoc": "^3.4.0", "rollup": "^0.36.3", "rollup-plugin-babel": "^2.6.1", + "rollup-plugin-flow": "^1.0.1", "rollup-plugin-uglify": "^1.0.1" } } diff --git a/rollup.config.js b/rollup.config.js index 6f44dbd..b5d0108 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,5 +1,6 @@ import babel from 'rollup-plugin-babel'; import uglify from 'rollup-plugin-uglify'; +import flow from 'rollup-plugin-flow'; export default { entry: 'js/main.js', @@ -7,6 +8,7 @@ export default { format: 'umd', moduleName: 'holmes', plugins: [ + flow(), babel({ babelrc: false, presets: ['es2015-rollup'] diff --git a/yarn.lock b/yarn.lock index 2e962be..e5b9a76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -614,7 +614,7 @@ babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.8. lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.11.0, babylon@^6.13.0: +babylon@^6.11.0, babylon@^6.13.0, babylon@^6.8.4: version "6.14.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" @@ -1215,6 +1215,12 @@ flow-bin@^0.35.0: version "0.35.0" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.35.0.tgz#63d4eb9582ce352541be98e6a424503217141b07" +flow-remove-types@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.0.5.tgz#c1c948d96a23f3f4012f1af0e6eb937898fcc968" + dependencies: + babylon "^6.8.4" + for-in@^0.1.5: version "0.1.6" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" @@ -2584,13 +2590,20 @@ rollup-plugin-babel@^2.6.1: object-assign "^4.1.0" rollup-pluginutils "^1.5.0" +rollup-plugin-flow@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-flow/-/rollup-plugin-flow-1.0.1.tgz#a63a27a3cec2ced9e20604f507f8edd9a1b93e01" + dependencies: + flow-remove-types "^1.0.0" + rollup-pluginutils "^1.5.1" + rollup-plugin-uglify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-1.0.1.tgz#11d0b0c8bcd2d07e6908f74fd16b0152390b922a" dependencies: uglify-js "^2.6.1" -rollup-pluginutils@^1.5.0: +rollup-pluginutils@^1.5.0, rollup-pluginutils@^1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" dependencies: @@ -2823,10 +2836,6 @@ tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" -to-factory@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-factory/-/to-factory-1.0.0.tgz#8738af8bd97120ad1d4047972ada5563bf9479b1" - to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320"