diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index e60dc13..0000000
--- a/.babelrc
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "modules": "umd",
- "loose": "all",
- "compact": true,
- "comments": false
-}
diff --git a/.editorconfig b/.editorconfig
index 9c378bd..f2fd6b8 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,15 +1,17 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
root = true
+# Unix-style newlines with a newline ending every file
+# Tab indent, JS style
[*]
-indent_style = tab
end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
insert_final_newline = true
+indent_size = 2
+indent_style = tab
-[{package.json,.*rc,*.yml}]
+# Circle YAML files need to have spaces not tabs
+[*.yml]
indent_style = space
indent_size = 2
-
-[*.md]
-trim_trailing_whitespace = false
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..9dfdcb9
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,37 @@
+{
+ "env": {
+ "browser": true,
+ "commonjs": true,
+ "es6": true,
+ "node": true,
+ "mocha": true
+ },
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "ecmaVersion": 2017
+ },
+ "globals": {
+ "mixpanel": true,
+ "serverVars": true,
+ "avkind": true,
+ "kind": true,
+ "Stripe": true
+ },
+ "plugins": [
+ "must-use-await"
+ ],
+ "rules": {
+ "curly": ["error", "all"],
+ "indent": [
+ "error",
+ "tab"
+ ],
+ "must-use-await/must-use-await": 1, // 1 warn, 2 error
+ "linebreak-style": "off",
+ "quotes": "off",
+ "no-console": "off",
+ "semi": "off",
+ "no-unused-vars": "off",
+ "no-debugger": "off"
+ }
+}
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 7d2a047..0000000
--- a/.jshintrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "esnext": true,
- "browser": true
-}
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 4ff8603..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Jason Miller
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index 80381e8..ece5b22 100644
--- a/README.md
+++ b/README.md
@@ -1,35 +1,12 @@
-tags-input
-==========
+## A fork of [tags-input](https://github.com/developit/tags-input)
-[![NPM Version](http://img.shields.io/npm/v/tags-input.svg?style=flat)](https://www.npmjs.org/package/tags-input)
-[![Bower Version](http://img.shields.io/bower/v/tags-input.svg?style=flat)](http://bower.io/search/?q=tags-input)
-[![Gitter Room](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/developit/tags-input)
+Slowly refactoring this module to add:
-**Features:**
+ - Plain CommonJS / ES2017 / SASS and eslint.
+ - Unminified variables, code run through [prettier](https://github.com/prettier/prettier-eslint-cli).
+ - Unit tests
-- I said `` should be a thing.
-- With full keyboard, mouse and focus support.
-- Works with HTML5 `pattern` and `placeholder` attributes, too!
-- Native [`change`](https://developer.mozilla.org/en-US/docs/Web/Events/change) and [`input`](https://developer.mozilla.org/en-US/docs/Web/Events/input) _("live" change)_ events.
-- Using [preact](https://github.com/developit/preact)? (or react?) There's a wrapper called [preact-token-input](https://github.com/developit/preact-token-input)
-- Works in modern browsers and IE10+
-
-**Screenshot:**
-
-> ![screenshot](http://cl.ly/image/3M3U1h1s2y0v/tags-screenshot.png)
-
-[JSFiddle Demo](http://jsfiddle.net/developit/d5w4jpxq/)
-
----
-
-
-Examples
-========
-
-It's easy to use! In addition to the example code, you'll also need to
-include `tags-input.css` - I didn't bundle it because that's a bit gross.
-
-**CommonJS:**
+## Usage
```js
var tagsInput = require('tags-input');
@@ -44,21 +21,7 @@ document.body.appendChild(tags);
tagsInput(document.querySelector('input[type="tags"]'));
// or just enhance all tag inputs on the page:
-[].forEach.call(document.querySelectorAll('input[type="tags"]'), tagsInput);
-```
-
-**HTML Example:**
-
-```html
-
-
-
-
-
-
+document.querySelectorAll('input[type="tags"]').forEach(function(element){
+ tagsInput(element)
+});
```
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 3cd2bf7..0000000
--- a/bower.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "tags-input",
- "version": "1.0.2",
- "homepage": "https://github.com/developit/tags-input",
- "authors": [
- "Jason Miller "
- ],
- "description": " like magic.",
- "main": "tags-input.js,tags-input.css",
- "moduleType": [
- "amd",
- "node",
- "globals"
- ],
- "keywords": [
- "tags",
- "input",
- "polyfill"
- ],
- "license": "MIT",
- "ignore": [
- "**/.*",
- "**/*.min.js",
- "src",
- "bower_components",
- "LICENSE",
- "package.json",
- "README.md"
- ]
-}
diff --git a/index.html b/index.html
deleted file mode 100644
index c049cb5..0000000
--- a/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..92d06b8
--- /dev/null
+++ b/index.js
@@ -0,0 +1,255 @@
+var SEPERATOR = require("./seperator.js");
+
+const BACKSPACE = 8,
+ TAB = 9,
+ ENTER = 13,
+ LEFT = 37,
+ RIGHT = 39,
+ DELETE = 46,
+ COMMA = 188;
+
+const COPY_PROPS = [
+ "placeholder",
+ "pattern",
+ "spellcheck",
+ "autocomplete",
+ "autocapitalize",
+ "autofocus",
+ "accessKey",
+ "accept",
+ "lang",
+ "minLength",
+ "maxLength",
+ "required"
+];
+
+function tagsInput(input) {
+ function createElement(type, name, text, attributes) {
+ let element = document.createElement(type);
+ if (name) element.className = name;
+ if (text) element.textContent = text;
+ for (let key in attributes) {
+ element.setAttribute(`data-${key}`, attributes[key]);
+ }
+ return element;
+ }
+
+ function select(selector, all) {
+ if (all) {
+ return document.querySelectorAll(selector);
+ }
+ return document.querySelector(selector);
+ }
+
+ function getValue() {
+ return select(".tag", true)
+ .map(tag => tag.textContent)
+ .concat(document.input.value || [])
+ .join(SEPERATOR);
+ }
+
+ function setValue(value) {
+ select(".tag", true).forEach(t => document.removeChild(t));
+ savePartialInput(value);
+ }
+
+ function save() {
+ input.value = getValue();
+ input.dispatchEvent(new Event("change"));
+ }
+
+ // Return false if no need to add a tag
+ function addTag(text) {
+ // Add multiple tags if the user pastes in data with SEPERATOR already in it
+ if (text.includes(SEPERATOR)) {
+ text = text.split(SEPERATOR);
+ }
+ if (Array.isArray(text)) {
+ return text.forEach(addTag);
+ }
+
+ let tag = text && text.trim();
+ // Ignore if text is empty
+ if (!tag) {
+ return false;
+ }
+
+ // Don't add if it's invalid (eg, for pattern=)
+ if (!document.input.checkValidity()) {
+ return false;
+ }
+
+ // For duplicates, briefly highlight the existing tag
+ if (!input.getAttribute("duplicates")) {
+ let existingTag = select(`[data-tag="${tag}"]`);
+ if (existingTag) {
+ existingTag.classList.add("dupe");
+ setTimeout(() => existingTag.classList.remove("dupe"), 100);
+ return false;
+ }
+ }
+
+ document.insertBefore(
+ createElement("span", "tag", tag, { tag }),
+ document.input
+ );
+ }
+
+ function select(element) {
+ let selectedElements = select(".selected");
+ if (selectedElements) selectedElements.classList.remove("selected");
+ if (element) element.classList.add("selected");
+ }
+
+ function setInputWidth() {
+ let last = select(".tag", true).pop(),
+ width = document.offsetWidth;
+ if (!width) return;
+ document.input.style.width =
+ Math.max(width - (last ? last.offsetLeft + last.offsetWidth : 5) - 5, width / 4) +
+ "px";
+ }
+
+ function savePartialInput(value) {
+ if (typeof value !== "string" && !Array.isArray(value)) {
+ // If the document input does not contain a value, default to the original element passed
+ value = document.input.value;
+ }
+ if (addTag(value) !== false) {
+ document.input.value = "";
+ save();
+ setInputWidth();
+ }
+ }
+
+ function refocus(event) {
+ if (event.target.classList.contains("tag")) select(event.target);
+ if (event.target === document.input) return select();
+ document.input.focus();
+ event.preventDefault();
+ return false;
+ }
+
+ function caretAtStart(element) {
+ try {
+ return element.selectionStart === 0 && element.selectionEnd === 0;
+ } catch (event) {
+ return element.value === "";
+ }
+ }
+
+ let document = createElement("div", "tags-input"),
+ sib = input.nextSibling;
+
+ input.parentNode[sib ? "insertBefore" : "appendChild"](document, sib);
+
+ input.style.cssText = "position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;";
+ input.tabIndex = -1;
+
+ let inputType = input.getAttribute("type");
+ if (!inputType || inputType === "tags") {
+ inputType = "text";
+ }
+ document.input = createElement("input");
+ document.input.setAttribute("type", inputType);
+ COPY_PROPS.forEach(prop => {
+ if (input[prop] !== document.input[prop]) {
+ document.input[prop] = input[prop];
+ try {
+ delete input[prop];
+ } catch (event) {}
+ }
+ });
+ document.appendChild(document.input);
+
+ input.addEventListener("focus", () => {
+ document.input.focus();
+ });
+
+ document.input.addEventListener("focus", () => {
+ document.classList.add("focus");
+ select();
+ });
+
+ document.input.addEventListener("blur", () => {
+ document.classList.remove("focus");
+ select();
+ savePartialInput();
+ });
+
+ document.input.addEventListener("keydown", event => {
+ let element = document.input,
+ key = event.keyCode || event.which,
+ selectedTag = select(".tag.selected"),
+ atStart = caretAtStart(element),
+ last = select(".tag", true).pop();
+
+ setInputWidth();
+
+ if (key === ENTER || key === COMMA || key === TAB) {
+ if (!element.value && key !== COMMA) return;
+ savePartialInput();
+ } else if (key === DELETE && selectedTag) {
+ if (selectedTag.nextSibling !== document.input)
+ select(selectedTag.nextSibling);
+ document.removeChild(selectedTag);
+ setInputWidth();
+ save();
+ } else if (key === BACKSPACE) {
+ if (selectedTag) {
+ select(selectedTag.previousSibling);
+ document.removeChild(selectedTag);
+ setInputWidth();
+ save();
+ } else if (last && atStart) {
+ select(last);
+ } else {
+ return;
+ }
+ } else if (key === LEFT) {
+ if (selectedTag) {
+ if (selectedTag.previousSibling) {
+ select(selectedTag.previousSibling);
+ }
+ } else if (!atStart) {
+ return;
+ } else {
+ select(last);
+ }
+ } else if (key === RIGHT) {
+ if (!selectedTag) return;
+ select(selectedTag.nextSibling);
+ } else {
+ return select();
+ }
+
+ event.preventDefault();
+ return false;
+ });
+
+ // Proxy "input" (live change) events , update the first tag live as the user types
+ // This means that users who only want one thing don't have to enter commas
+ document.input.addEventListener("input", () => {
+ input.value = getValue();
+ input.dispatchEvent(new Event("input"));
+ });
+
+ // One tick after pasting, parse pasted text as CSV:
+ document.input.addEventListener("paste", () =>
+ setTimeout(savePartialInput, 0)
+ );
+
+ document.addEventListener("mousedown", refocus);
+ document.addEventListener("touchstart", refocus);
+
+ document.setValue = setValue;
+ document.getValue = getValue;
+
+ // Add tags for existing values
+ savePartialInput(input.value);
+}
+
+// make life easier:
+tagsInput.enhance = tagsInput.tagsInput = tagsInput;
+
+module.exports = tagsInput;
diff --git a/src/tags-input.less b/index.sass
similarity index 100%
rename from src/tags-input.less
rename to index.sass
diff --git a/package.json b/package.json
index eff354e..70b4e0e 100644
--- a/package.json
+++ b/package.json
@@ -1,28 +1,17 @@
{
- "name": "tags-input",
- "version": "1.1.1",
- "main": "tags-input.js",
- "description": " like magic.",
- "scripts": {
- "build": "npm run transpile && npm run less && npm run size",
- "transpile": "babel src --source-root src -s -d .",
- "less": "lessc --clean-css --source-map --source-map-less-inline --autoprefix=\"last 2 versions\" src/tags-input.less tags-input.css",
- "size": "echo \"gzip size: $(pretty-bytes $(gzip-size $npm_package_main))\"",
- "test": "jshint src/**.js",
- "prepublish": "npm run build",
- "release": "npm run build && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/developit/tags-input.git"
- },
- "devDependencies": {
- "babel": "^5.8.21",
- "gzip-size": "^3.0.0",
- "jshint": "^2.8.0",
- "less": "^2.5.1",
- "less-plugin-autoprefix": "^1.4.2",
- "less-plugin-clean-css": "^1.5.1",
- "pretty-bytes": "^2.0.1"
- }
+ "name": "@mikemaccana/tags-input",
+ "version": "2.0.1",
+ "main": "tags-input.js",
+ "description": "Refactor of @developit's tags input.",
+ "scripts": {
+ "test": "mocha"
+ },
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/mikemaccana/tags-input.git"
+ },
+ "devDependencies": {
+ "dedent-js": "^1.0.1"
+ }
}
diff --git a/seperator.js b/seperator.js
new file mode 100644
index 0000000..6339ab3
--- /dev/null
+++ b/seperator.js
@@ -0,0 +1,4 @@
+// Either of commma, space or newline, followed by 0 or more spaces.
+const SEPERATOR = /[, \n] */;
+
+module.exports = SEPERATOR;
\ No newline at end of file
diff --git a/src/tags-input.js b/src/tags-input.js
deleted file mode 100644
index 4f5e07a..0000000
--- a/src/tags-input.js
+++ /dev/null
@@ -1,233 +0,0 @@
-const BACKSPACE = 8,
- TAB = 9,
- ENTER = 13,
- LEFT = 37,
- RIGHT = 39,
- DELETE = 46,
- COMMA = 188;
-
-const SEPERATOR = ',';
-
-const COPY_PROPS = 'placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');
-
-export default function tagsInput(input) {
- function createElement(type, name, text, attributes) {
- let el = document.createElement(type);
- if (name) el.className = name;
- if (text) el.textContent = text;
- for (let key in attributes) {
- el.setAttribute(`data-${key}`, attributes[key]);
- }
- return el;
- }
-
- function $(selector, all) {
- return all===true ? Array.prototype.slice.call(base.querySelectorAll(selector)) : base.querySelector(selector);
- }
-
- function getValue() {
- return $('.tag', true)
- .map( tag => tag.textContent )
- .concat(base.input.value || [])
- .join(SEPERATOR);
- }
-
- function setValue(value) {
- $('.tag', true).forEach( t => base.removeChild(t) );
- savePartialInput(value);
- }
-
- function save() {
- input.value = getValue();
- input.dispatchEvent(new Event('change'));
- }
-
- // Return false if no need to add a tag
- function addTag(text) {
- // Add multiple tags if the user pastes in data with SEPERATOR already in it
- if (~text.indexOf(SEPERATOR)) text = text.split(SEPERATOR);
- if (Array.isArray(text)) return text.forEach(addTag);
-
- let tag = text && text.trim();
- // Ignore if text is empty
- if (!tag) return false;
-
- // For duplicates, briefly highlight the existing tag
- if (!input.getAttribute('duplicates')) {
- let exisingTag = $(`[data-tag="${tag}"]`);
- if (exisingTag) {
- exisingTag.classList.add('dupe');
- setTimeout( () => exisingTag.classList.remove('dupe') , 100);
- return false;
- }
- }
-
- base.insertBefore(
- createElement('span', 'tag', tag, { tag }),
- base.input
- );
- }
-
- function select(el) {
- let sel = $('.selected');
- if (sel) sel.classList.remove('selected');
- if (el) el.classList.add('selected');
- }
-
- function setInputWidth() {
- let last = $('.tag',true).pop(),
- w = base.offsetWidth;
- if (!w) return;
- base.input.style.width = Math.max(
- w - (last ? (last.offsetLeft+last.offsetWidth) : 5) - 5,
- w/4
- ) + 'px';
- }
-
- function savePartialInput(value) {
- if (typeof value!=='string' && !Array.isArray(value)) {
- // If the base input does not contain a value, default to the original element passed
- value = base.input.value;
- }
- if (addTag(value)!==false) {
- base.input.value = '';
- save();
- setInputWidth();
- }
- }
-
- function refocus(e) {
- if (e.target.classList.contains('tag')) select(e.target);
- if (e.target===base.input) return select();
- base.input.focus();
- e.preventDefault();
- return false;
- }
-
- function caretAtStart(el) {
- try {
- return el.selectionStart === 0 && el.selectionEnd === 0;
- }
- catch(e) {
- return el.value === '';
- }
- }
-
-
- let base = createElement('div', 'tags-input'),
- sib = input.nextSibling;
-
- input.parentNode[sib?'insertBefore':'appendChild'](base, sib);
-
- input.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';
- input.tabIndex = -1;
-
- let inputType = input.getAttribute('type');
- if (!inputType || inputType === 'tags') {
- inputType = 'text';
- }
- base.input = createElement('input');
- base.input.setAttribute('type', inputType);
- COPY_PROPS.forEach( prop => {
- if (input[prop]!==base.input[prop]) {
- base.input[prop] = input[prop];
- try { delete input[prop]; }catch(e){}
- }
- });
- base.appendChild(base.input);
-
- input.addEventListener('focus', () => {
- base.input.focus();
- });
-
- base.input.addEventListener('focus', () => {
- base.classList.add('focus');
- select();
- });
-
- base.input.addEventListener('blur', () => {
- base.classList.remove('focus');
- select();
- savePartialInput();
- });
-
- base.input.addEventListener('keydown', e => {
- let el = base.input,
- key = e.keyCode || e.which,
- selectedTag = $('.tag.selected'),
- atStart = caretAtStart(el),
- last = $('.tag',true).pop();
-
- setInputWidth();
-
- if (key===ENTER || key===COMMA || key===TAB) {
- if (!el.value && key!==COMMA) return;
- savePartialInput();
- }
- else if (key===DELETE && selectedTag) {
- if (selectedTag.nextSibling!==base.input) select(selectedTag.nextSibling);
- base.removeChild(selectedTag);
- setInputWidth();
- save();
- }
- else if (key===BACKSPACE) {
- if (selectedTag) {
- select(selectedTag.previousSibling);
- base.removeChild(selectedTag);
- setInputWidth();
- save();
- }
- else if (last && atStart) {
- select(last);
- }
- else {
- return;
- }
- }
- else if (key===LEFT) {
- if (selectedTag) {
- if (selectedTag.previousSibling) {
- select(selectedTag.previousSibling);
- }
- }
- else if (!atStart) {
- return;
- }
- else {
- select(last);
- }
- }
- else if (key===RIGHT) {
- if (!selectedTag) return;
- select(selectedTag.nextSibling);
- }
- else {
- return select();
- }
-
- e.preventDefault();
- return false;
- });
-
- // Proxy "input" (live change) events , update the first tag live as the user types
- // This means that users who only want one thing don't have to enter commas
- base.input.addEventListener('input', () => {
- input.value = getValue();
- input.dispatchEvent(new Event('input'));
- });
-
- // One tick after pasting, parse pasted text as CSV:
- base.input.addEventListener('paste', () => setTimeout(savePartialInput, 0));
-
- base.addEventListener('mousedown', refocus);
- base.addEventListener('touchstart', refocus);
-
- base.setValue = setValue;
- base.getValue = getValue;
-
- // Add tags for existing values
- savePartialInput(input.value);
-}
-
-// make life easier:
-tagsInput.enhance = tagsInput.tagsInput = tagsInput;
diff --git a/tags-input.css b/tags-input.css
deleted file mode 100644
index ef4477b..0000000
--- a/tags-input.css
+++ /dev/null
@@ -1,2 +0,0 @@
-.tags-input{display:inline-block;padding:0 2px;background:#FFF;border:1px solid #CCC;width:16em;border-radius:2px;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.tags-input .tag{display:inline-block;background:#EEE;color:#444;padding:0 4px;margin:2px;border:1px solid #CCC;border-radius:2px;font:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;transition:all .1s ease}.tags-input .tag.selected{background-color:#777;border-color:#777;color:#EEE}.tags-input .tag.dupe{-webkit-transform:scale3d(1.2,1.2,1.2);transform:scale3d(1.2,1.2,1.2);background-color:#FCC;border-color:#700}.tags-input input{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;display:inline-block!important;padding:3px;margin:0!important;background:0 0!important;border:none!important;box-shadow:none!important;font:inherit!important;font-size:100%!important;outline:0!important}.tags-input .selected~input{opacity:.3}
-/*# sourceMappingURL=tags-input.css.map */
\ No newline at end of file
diff --git a/tags-input.css.map b/tags-input.css.map
deleted file mode 100644
index a64b6a0..0000000
--- a/tags-input.css.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["src/tags-input.less"],"names":[],"mappings":"AAAA,YACC,qBACA,cACA,gBACA,sBACA,WACA,kBACA,yCAAA,CAEA,iBACC,qBACA,gBACA,WACA,cACA,WACA,sBACA,kBACA,aACA,yBACA,AADA,sBACA,AADA,qBACA,AADA,iBACA,eACA,uBAAA,CAEC,0BACA,sBACA,kBACA,UAAA,CAGA,sBACA,uCACA,AADA,+BACA,sBACA,iBAAA,CAIF,kBACC,kCACA,AADA,+BACA,AADA,0BACA,+BACA,YACA,mBACA,yBACA,sBACA,0BACA,uBACA,yBACA,mBAAA,CAGS,4BACT,UAAA,CAAA","file":"tags-input.css","sourcesContent":[".tags-input {\n\tdisplay: inline-block;\n\tpadding: 0 2px;\n\tbackground: #FFF;\n\tborder: 1px solid #CCC;\n\twidth: 16em;\n\tborder-radius: 2px;\n\tbox-shadow: inset 0 1px 2px rgba(0,0,0,0.1);\n\n\t.tag {\n\t\tdisplay: inline-block;\n\t\tbackground: #EEE;\n\t\tcolor: #444;\n\t\tpadding: 0 4px;\n\t\tmargin: 2px;\n\t\tborder: 1px solid #CCC;\n\t\tborder-radius: 2px;\n\t\tfont: inherit;\n\t\tuser-select: none;\n\t\tcursor: pointer;\n\t\ttransition: all 100ms ease;\n\n\t\t&.selected {\n\t\t\tbackground-color: #777;\n\t\t\tborder-color: #777;\n\t\t\tcolor: #EEE;\n\t\t}\n\n\t\t&.dupe {\n\t\t\ttransform: scale3d(1.2,1.2,1.2);\n\t\t\tbackground-color: #FCC;\n\t\t\tborder-color: #700;\n\t\t}\n\t}\n\n\tinput {\n\t\tappearance: none !important;\n\t\tdisplay: inline-block !important;\n\t\tpadding: 3px;\n\t\tmargin: 0 !important;\n\t\tbackground: none !important;\n\t\tborder: none !important;\n\t\tbox-shadow: none !important;\n\t\tfont: inherit !important;\n\t\tfont-size: 100% !important;\n\t\toutline: none !important;\n\t}\n\n\t.selected ~ input {\n\t\topacity: 0.3;\n\t}\n}\n"]}
\ No newline at end of file
diff --git a/tags-input.js b/tags-input.js
deleted file mode 100644
index 7abf0e5..0000000
--- a/tags-input.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','module'],factory);}else if(typeof exports !== 'undefined' && typeof module !== 'undefined'){factory(exports,module);}else {var mod={exports:{}};factory(mod.exports,mod);global.tagsInput = mod.exports;}})(this,function(exports,module){'use strict';module.exports = tagsInput;var BACKSPACE=8,TAB=9,ENTER=13,LEFT=37,RIGHT=39,DELETE=46,COMMA=188;var SEPERATOR=',';var COPY_PROPS='placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');function tagsInput(input){function createElement(type,name,text,attributes){var el=document.createElement(type);if(name)el.className = name;if(text)el.textContent = text;for(var key in attributes) {el.setAttribute('data-' + key,attributes[key]);}return el;}function $(selector,all){return all === true?Array.prototype.slice.call(base.querySelectorAll(selector)):base.querySelector(selector);}function getValue(){return $('.tag',true).map(function(tag){return tag.textContent;}).concat(base.input.value || []).join(SEPERATOR);}function setValue(value){$('.tag',true).forEach(function(t){return base.removeChild(t);});savePartialInput(value);}function save(){input.value = getValue();input.dispatchEvent(new Event('change'));}function addTag(text){if(~text.indexOf(SEPERATOR))text = text.split(SEPERATOR);if(Array.isArray(text))return text.forEach(addTag);var tag=text && text.trim();if(!tag)return false;if(!input.getAttribute('duplicates')){var _ret=(function(){var exisingTag=$('[data-tag="' + tag + '"]');if(exisingTag){exisingTag.classList.add('dupe');setTimeout(function(){return exisingTag.classList.remove('dupe');},100);return {v:false};}})();if(typeof _ret === 'object')return _ret.v;}base.insertBefore(createElement('span','tag',tag,{tag:tag}),base.input);}function select(el){var sel=$('.selected');if(sel)sel.classList.remove('selected');if(el)el.classList.add('selected');}function setInputWidth(){var last=$('.tag',true).pop(),w=base.offsetWidth;if(!w)return;base.input.style.width = Math.max(w - (last?last.offsetLeft + last.offsetWidth:5) - 5,w / 4) + 'px';}function savePartialInput(value){if(typeof value !== 'string' && !Array.isArray(value)){value = base.input.value;}if(addTag(value) !== false){base.input.value = '';save();setInputWidth();}}function refocus(e){if(e.target.classList.contains('tag'))select(e.target);if(e.target === base.input)return select();base.input.focus();e.preventDefault();return false;}var base=createElement('div','tags-input'),sib=input.nextSibling;input.parentNode[sib?'insertBefore':'appendChild'](base,sib);input.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';input.tabIndex = -1;base.input = createElement('input');base.input.setAttribute('type','text');COPY_PROPS.forEach(function(prop){if(input[prop] !== base.input[prop]){base.input[prop] = input[prop];try{delete input[prop];}catch(e) {}}});base.appendChild(base.input);input.addEventListener('focus',function(){base.input.focus();});base.input.addEventListener('focus',function(){base.classList.add('focus');select();});base.input.addEventListener('blur',function(){base.classList.remove('focus');select();savePartialInput();});base.input.addEventListener('keydown',function(e){var el=base.input,key=e.keyCode || e.which,selectedTag=$('.tag.selected'),pos=el.selectionStart === el.selectionEnd && el.selectionStart,last=$('.tag',true).pop();setInputWidth();if(key === ENTER || key === COMMA || key === TAB){if(!el.value && key !== COMMA)return;savePartialInput();}else if(key === DELETE && selectedTag){if(selectedTag.nextSibling !== base.input)select(selectedTag.nextSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(key === BACKSPACE){if(selectedTag){select(selectedTag.previousSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(last && pos === 0){select(last);}else {return;}}else if(key === LEFT){if(selectedTag){if(selectedTag.previousSibling){select(selectedTag.previousSibling);}}else if(pos !== 0){return;}else {select(last);}}else if(key === RIGHT){if(!selectedTag)return;select(selectedTag.nextSibling);}else {return select();}e.preventDefault();return false;});base.input.addEventListener('input',function(){input.value = getValue();input.dispatchEvent(new Event('input'));});base.input.addEventListener('paste',function(){return setTimeout(savePartialInput,0);});base.addEventListener('mousedown',refocus);base.addEventListener('touchstart',refocus);base.setValue = setValue;base.getValue = getValue;savePartialInput(input.value);}tagsInput.enhance = tagsInput.tagsInput = tagsInput;});
-//# sourceMappingURL=tags-input.js.map
\ No newline at end of file
diff --git a/tags-input.js.map b/tags-input.js.map
deleted file mode 100644
index 29ab320..0000000
--- a/tags-input.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["src/tags-input.js"],"names":[],"mappings":"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","file":"tags-input.js","sourceRoot":"src","sourcesContent":["const BACKSPACE = 8,\n\tTAB = 9,\n\tENTER = 13,\n\tLEFT = 37,\n\tRIGHT = 39,\n\tDELETE = 46,\n\tCOMMA = 188;\n\nconst SEPERATOR = ',';\n\nconst COPY_PROPS = 'placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');\n\nexport default function tagsInput(input) {\n\tfunction createElement(type, name, text, attributes) {\n\t\tlet el = document.createElement(type);\n\t\tif (name) el.className = name;\n\t\tif (text) el.textContent = text;\n\t\tfor (let key in attributes) {\n\t\t\tel.setAttribute(`data-${key}`, attributes[key]);\n\t\t}\n\t\treturn el;\n\t}\n\n\tfunction $(selector, all) {\n\t\treturn all===true ? Array.prototype.slice.call(base.querySelectorAll(selector)) : base.querySelector(selector);\n\t}\n\n\tfunction getValue() {\n\t\treturn $('.tag', true)\n\t\t\t.map( tag => tag.textContent )\n\t\t\t.concat(base.input.value || [])\n\t\t\t.join(SEPERATOR);\n\t}\n\n\tfunction setValue(value) {\n\t\t$('.tag', true).forEach( t => base.removeChild(t) );\n\t\tsavePartialInput(value);\n\t}\n\n\tfunction save() {\n\t\tinput.value = getValue();\n\t\tinput.dispatchEvent(new Event('change'));\n\t}\n\n\t// Return false if no need to add a tag\n\tfunction addTag(text) {\n\t\t// Add multiple tags if the user pastes in data with SEPERATOR already in it\n\t\tif (~text.indexOf(SEPERATOR)) text = text.split(SEPERATOR);\n\t\tif (Array.isArray(text)) return text.forEach(addTag);\n\n\t\tlet tag = text && text.trim();\n\t\t// Ignore if text is empty\n\t\tif (!tag) return false;\n\n\t\t// For duplicates, briefly highlight the existing tag\n\t\tif (!input.getAttribute('duplicates')) {\n\t\t\tlet exisingTag = $(`[data-tag=\"${tag}\"]`);\n\t\t\tif (exisingTag) {\n\t\t\t\texisingTag.classList.add('dupe');\n\t\t\t\tsetTimeout( () => exisingTag.classList.remove('dupe') , 100);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tbase.insertBefore(\n\t\t\tcreateElement('span', 'tag', tag, { tag }),\n\t\t\tbase.input\n\t\t);\n\t}\n\n\tfunction select(el) {\n\t\tlet sel = $('.selected');\n\t\tif (sel) sel.classList.remove('selected');\n\t\tif (el) el.classList.add('selected');\n\t}\n\n\tfunction setInputWidth() {\n\t\tlet last = $('.tag',true).pop(),\n\t\t\tw = base.offsetWidth;\n\t\tif (!w) return;\n\t\tbase.input.style.width = Math.max(\n\t\t\tw - (last ? (last.offsetLeft+last.offsetWidth) : 5) - 5,\n\t\t\tw/4\n\t\t) + 'px';\n\t}\n\n\tfunction savePartialInput(value) {\n\t\tif (typeof value!=='string' && !Array.isArray(value)) {\n\t\t\t// If the base input does not contain a value, default to the original element passed\n\t\t\tvalue = base.input.value;\n\t\t}\n\t\tif (addTag(value)!==false) {\n\t\t\tbase.input.value = '';\n\t\t\tsave();\n\t\t\tsetInputWidth();\n\t\t}\n\t}\n\n\tfunction refocus(e) {\n\t\tif (e.target.classList.contains('tag')) select(e.target);\n\t\tif (e.target===base.input) return select();\n\t\tbase.input.focus();\n\t\te.preventDefault();\n\t\treturn false;\n\t}\n\n\tlet base = createElement('div', 'tags-input'),\n\t\tsib = input.nextSibling;\n\tinput.parentNode[sib?'insertBefore':'appendChild'](base, sib);\n\n\tinput.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';\n\tinput.tabIndex = -1;\n\n\tbase.input = createElement('input');\n\tbase.input.setAttribute('type', 'text');\n\tCOPY_PROPS.forEach( prop => {\n\t\tif (input[prop]!==base.input[prop]) {\n\t\t\tbase.input[prop] = input[prop];\n\t\t\ttry { delete input[prop]; }catch(e){}\n\t\t}\n\t});\n\tbase.appendChild(base.input);\n\n\tinput.addEventListener('focus', () => {\n\t\tbase.input.focus();\n\t});\n\n\tbase.input.addEventListener('focus', () => {\n\t\tbase.classList.add('focus');\n\t\tselect();\n\t});\n\n\tbase.input.addEventListener('blur', () => {\n\t\tbase.classList.remove('focus');\n\t\tselect();\n\t\tsavePartialInput();\n\t});\n\n\tbase.input.addEventListener('keydown', e => {\n\t\tlet el = base.input,\n\t\t\tkey = e.keyCode || e.which,\n\t\t\tselectedTag = $('.tag.selected'),\n\t\t\tpos = el.selectionStart===el.selectionEnd && el.selectionStart,\n\t\t\tlast = $('.tag',true).pop();\n\n\t\tsetInputWidth();\n\n\t\tif (key===ENTER || key===COMMA || key===TAB) {\n\t\t\tif (!el.value && key!==COMMA) return;\n\t\t\tsavePartialInput();\n\t\t}\n\t\telse if (key===DELETE && selectedTag) {\n\t\t\tif (selectedTag.nextSibling!==base.input) select(selectedTag.nextSibling);\n\t\t\tbase.removeChild(selectedTag);\n\t\t\tsetInputWidth();\n\t\t\tsave();\n\t\t}\n\t\telse if (key===BACKSPACE) {\n\t\t\tif (selectedTag) {\n\t\t\t\tselect(selectedTag.previousSibling);\n\t\t\t\tbase.removeChild(selectedTag);\n\t\t\t\tsetInputWidth();\n\t\t\t\tsave();\n\t\t\t}\n\t\t\telse if (last && pos===0) {\n\t\t\t\tselect(last);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse if (key===LEFT) {\n\t\t\tif (selectedTag) {\n\t\t\t\tif (selectedTag.previousSibling) {\n\t\t\t\t\tselect(selectedTag.previousSibling);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (pos!==0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tselect(last);\n\t\t\t}\n\t\t}\n\t\telse if (key===RIGHT) {\n\t\t\tif (!selectedTag) return;\n\t\t\tselect(selectedTag.nextSibling);\n\t\t}\n\t\telse {\n\t\t\treturn select();\n\t\t}\n\n\t\te.preventDefault();\n\t\treturn false;\n\t});\n\n\t// Proxy \"input\" (live change) events , update the first tag live as the user types\n\t// This means that users who only want one thing don't have to enter commas\n\tbase.input.addEventListener('input', () => {\n\t\tinput.value = getValue();\n\t\tinput.dispatchEvent(new Event('input'));\n\t});\n\n\t// One tick after pasting, parse pasted text as CSV:\n\tbase.input.addEventListener('paste', () => setTimeout(savePartialInput, 0));\n\n\tbase.addEventListener('mousedown', refocus);\n\tbase.addEventListener('touchstart', refocus);\n\n\tbase.setValue = setValue;\n\tbase.getValue = getValue;\n\n\t// Add tags for existing values\n\tsavePartialInput(input.value);\n}\n\n// make life easier:\ntagsInput.enhance = tagsInput.tagsInput = tagsInput;\n"]}
\ No newline at end of file
diff --git a/test/mocha.opts b/test/mocha.opts
new file mode 100644
index 0000000..b1374cc
--- /dev/null
+++ b/test/mocha.opts
@@ -0,0 +1,2 @@
+--ui tdd
+--bail
diff --git a/test/tests.js b/test/tests.js
new file mode 100644
index 0000000..0ee6db9
--- /dev/null
+++ b/test/tests.js
@@ -0,0 +1,63 @@
+// Tests. Mocha TDD/assert style. See
+// http://visionmedia.github.com/mocha/
+// http://nodejs.org/docs/latest/api/assert.html
+
+var assert = require('assert'),
+ SEPERATOR = require('../seperator.js'),
+ dedent = require('dedent-js'),
+ log = console.log.bind(console)
+
+var splitText = function(text){
+ return text.split(SEPERATOR)
+}
+
+suite('Splits strings to arrays', function(){
+ this.timeout(5 * 1000);
+ test('cleans comma', function(){
+ var input = 'one.com two.com three.com'
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+ test('cleans comma and space', function(){
+ var input = 'one.com, two.com, three.com'
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+ test('cleans comma only', function(){
+ var input = 'one.com,two.com,three.com'
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+ test('cleans newline', function(){
+ var input = dedent(`
+ one.com
+ two.com
+ three.com
+ `)
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+ test('cleans spaces', function(){
+ var input = 'one.com two.com three.com'
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+ test('cleans multiple spaces', function(){
+ var input = 'one.com two.com three.com'
+ var actual = splitText(input)
+ var expected = ['one.com', 'two.com', 'three.com']
+ assert.deepEqual(actual, expected)
+ });
+
+
+});
\ No newline at end of file