├── src ├── docs │ ├── themes │ │ └── creativebulma │ │ │ ├── layouts │ │ │ ├── _default │ │ │ │ ├── list.html │ │ │ │ ├── _markup │ │ │ │ │ └── render-link.html │ │ │ │ ├── baseof.html │ │ │ │ └── single.html │ │ │ ├── partials │ │ │ │ ├── header.html │ │ │ │ ├── footer.html │ │ │ │ ├── head.html │ │ │ │ ├── navbar.html │ │ │ │ └── menu.html │ │ │ ├── shortcodes │ │ │ │ ├── notification.html │ │ │ │ ├── changelog.html │ │ │ │ ├── link.html │ │ │ │ ├── tab.html │ │ │ │ ├── button.html │ │ │ │ ├── variables.html │ │ │ │ ├── table.html │ │ │ │ ├── options.html │ │ │ │ ├── tabs.html │ │ │ │ ├── preview.html │ │ │ │ ├── tag.html │ │ │ │ └── api.html │ │ │ ├── index.html │ │ │ └── 404.html │ │ │ ├── archetypes │ │ │ ├── default.md │ │ │ └── changelog.md │ │ │ ├── static │ │ │ ├── images │ │ │ │ └── clippy.svg │ │ │ ├── js │ │ │ │ ├── docs.js │ │ │ │ └── clipboard.min.js │ │ │ └── css │ │ │ │ └── docs.css │ │ │ ├── theme.toml │ │ │ └── LICENSE │ ├── archetypes │ │ └── default.md │ ├── data │ │ ├── versions.json │ │ ├── social.json │ │ ├── variables.json │ │ ├── events.json │ │ └── options.json │ ├── content │ │ ├── changelog.md │ │ ├── release │ │ │ ├── 1.0.1.md │ │ │ ├── 1.md │ │ │ └── 1.0.2.md │ │ ├── _index.md │ │ ├── how-to │ │ │ └── customize.md │ │ └── get-started │ │ │ ├── installation.md │ │ │ ├── javascript-api.md │ │ │ └── usage.md │ ├── layouts │ │ └── partials │ │ │ ├── footer.html │ │ │ └── head.html │ ├── config.toml │ └── static │ │ └── css │ │ └── bulma-tagsinput.min.css ├── js │ ├── utils │ │ ├── uuid.js │ │ ├── type.js │ │ ├── dom.js │ │ ├── component.js │ │ └── events.js │ ├── templates │ │ ├── dropdown-item.js │ │ ├── tag.js │ │ └── wrapper.js │ └── defaultOptions.js └── sass │ └── index.sass ├── .gitignore ├── docs ├── images │ └── clippy.svg ├── tags │ └── index.xml ├── categories │ └── index.xml ├── 404.html ├── how-to │ ├── index.xml │ └── customize │ │ └── index.html ├── release │ ├── 1 │ │ └── index.html │ ├── index.xml │ ├── 1.0.1 │ │ └── index.html │ └── 1.0.2 │ │ └── index.html ├── sitemap.xml ├── js │ ├── docs.js │ └── clipboard.min.js ├── get-started │ └── index.xml ├── css │ ├── bulma-tagsinput.min.css │ └── docs.css ├── index.xml ├── index.html └── changelog │ └── index.html ├── .eslintrc ├── babel.config.js ├── webpack.config.js ├── LICENSE ├── README.md ├── package.json ├── dist └── css │ └── bulma-tagsinput.min.css └── gulpfile.js /src/docs/themes/creativebulma/layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/partials/header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | package-lock.json 3 | 4 | node_modules 5 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/archetypes/default.md: -------------------------------------------------------------------------------- 1 | +++ 2 | +++ 3 | -------------------------------------------------------------------------------- /src/docs/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /src/docs/data/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "version": "v1.0", 4 | "url": "https://demo.creativebulma.net/components/tagsinput/1.0/" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /src/docs/content/changelog.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Changelog" 3 | date: "2020-05-02" 4 | menu: "main" 5 | weight: 100 6 | draft: false 7 | --- 8 | 9 | # Changelog 10 | 11 | {{< changelog >}} 12 | -------------------------------------------------------------------------------- /src/docs/data/social.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "github", 4 | "title" : "Github repository", 5 | "url": "https://github.com/CreativeBulma/bulma-tagsinput" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/js/utils/uuid.js: -------------------------------------------------------------------------------- 1 | export default (prefix = '') => prefix + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/notification.html: -------------------------------------------------------------------------------- 1 | {{ $_hugo_config := `{ "version": 1 }` }} 2 |
{{ .Inner | $.Page.RenderString }}
-------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/_default/_markup/render-link.html: -------------------------------------------------------------------------------- 1 | {{ .Text | safeHTML }} -------------------------------------------------------------------------------- /src/js/templates/dropdown-item.js: -------------------------------------------------------------------------------- 1 | import { escape } from "../utils/dom"; 2 | 3 | export default (data) => { 4 | return `${escape(data.text)}`; 5 | }; 6 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ block "footer_js" . }}{{ end }} 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/js/templates/tag.js: -------------------------------------------------------------------------------- 1 | import { escape } from "../utils/dom"; 2 | 3 | export default (data) => { 4 | return ` 5 | ${escape(data.text)} 6 | ${data.removable ? '
' : ''} 7 |
`; 8 | }; 9 | -------------------------------------------------------------------------------- /src/docs/data/variables.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "$tagsinput-selected-background-color", 4 | "description": "", 5 | "value": "$primary" 6 | }, 7 | { 8 | "name": "$tagsinput-duplicate-animation", 9 | "description": "", 10 | "value": "blinker .75s linear infinite" 11 | } 12 | ] -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/_default/baseof.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{- partial "head.html" . -}} 4 | 5 | {{- partial "header.html" . -}} 6 |
7 | {{- block "main" . }}{{- end }} 8 |
9 | {{- partial "footer.html" . -}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/docs/content/release/1.0.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "changelog" 3 | title: "(2020-05-07)" 4 | date: 2020-05-07T10:46:47+02:00 5 | weight: 1 6 | version: v1.0.1 7 | draft: false 8 | --- 9 | 10 | **Important fix for Form data** 11 | - {{< tag fixed >}} {{% link text="Duplicate form data when submitting" href="https://github.com/CreativeBulma/bulma-tagsinput/issues/1" target="_blank" %}} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/archetypes/changelog.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "({{ now.Format "2006-01-02" }})" 3 | subtitle: created on {{ now.Format "2006-01-02" }} 4 | date: {{ .Date }} 5 | weight: 6 | version: 7 | draft: true 8 | --- 9 | 10 | 11 | - {{< tag added >}} New functionality 12 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/changelog.html: -------------------------------------------------------------------------------- 1 | {{ range where .Site.RegularPages.ByDate.Reverse "Section" "release" }} 2 |
3 |
4 |

5 | {{ .Params.Version }} {{ .Title }} 6 |

7 | {{ .Params.Subtitle }} 8 |
9 | {{ .Content }} 10 |
11 |
12 |
13 | {{ end }} 14 | -------------------------------------------------------------------------------- /src/docs/content/release/1.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "changelog" 3 | title: "(2020-05-02)" 4 | date: 2020-05-02T10:46:47+02:00 5 | weight: 1 6 | version: v1.0.0 7 | draft: false 8 | --- 9 | 10 | **First working version** 11 | - {{< tag added >}} Works with Input, Select, Multiple Select elements 12 | - {{< tag added >}} Customize behavior with lots of options 13 | - {{< tag added >}} Events API 14 | - {{< tag added >}} External data source management 15 | - {{< tag added >}} Filtering/Search -------------------------------------------------------------------------------- /docs/images/clippy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/js/templates/wrapper.js: -------------------------------------------------------------------------------- 1 | import { escape } from "../utils/dom"; 2 | 3 | export default (data) => { 4 | return `
5 | 6 | 11 |
`; 12 | }; 13 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/link.html: -------------------------------------------------------------------------------- 1 | {{ $_hugo_config := `{ "version": 1 }` }} 2 | {{ $ref := "" }} 3 | {{ $target := "" }} 4 | {{ with .Get "href" }} 5 | {{ $ref = . }} 6 | {{ end }} 7 | {{ with .Get "target" }} 8 | {{ $target = . }} 9 | {{ end }} 10 | {{ with .Get "relref" }} 11 | {{ $ref = relref $ . }} 12 | {{ end }} 13 | {{ with .Get "text" }}{{ . }}{{ end }} -------------------------------------------------------------------------------- /src/docs/layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | {{ block "footer_js" . }}{{ end }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/static/images/clippy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/docs/config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "https://bulma-tagsinput.netlify.app/" 2 | languageCode = "en-us" 3 | title = "BulmaTagsInput" 4 | theme = "creativebulma" 5 | 6 | [markup] 7 | [markup.highlight] 8 | style = "manni" 9 | 10 | [params] 11 | version = "1.0" 12 | 13 | [menu] 14 | 15 | [[menu.main]] 16 | identifier = "get-started" 17 | name = "Get started" 18 | url = "/get-started/" 19 | weight = 10 20 | 21 | [[menu.main]] 22 | identifier = "how-to" 23 | name = "How-To" 24 | url = "#" 25 | weight = 20 26 | -------------------------------------------------------------------------------- /src/docs/content/release/1.0.2.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "changelog" 3 | title: "(2020-05-15)" 4 | date: 2020-05-15T10:46:47+02:00 5 | weight: 1 6 | version: v1.0.2 7 | draft: false 8 | --- 9 | 10 | **Important fixes for select based TagsInput** 11 | - {{< tag fixed >}} {{% link text="Multiple pre-selected options not working" href="https://github.com/CreativeBulma/bulma-tagsinput/issues/2" target="_blank" %}} 12 | - {{< tag fixed >}} {{% link text="Tags still removable when select is disabled" href="https://github.com/CreativeBulma/bulma-tagsinput/issues/3" target="_blank" %}} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/tab.html: -------------------------------------------------------------------------------- 1 | {{ $tab := .Get "tabNum" }} 2 | {{ $tabID := print (.Parent.Get "tabID") $tab }} 3 | {{ $tabName := (print "tabName" $tab) }} 4 | 5 | {{ if eq $tab "1" }} 6 |
7 | {{ $.Page.RenderString $.Inner }} 8 |
9 | 10 | {{ else }} 11 | 12 |
13 | {{ $.Page.RenderString $.Inner }} 14 |
15 | 16 | {{ end }} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/theme.toml: -------------------------------------------------------------------------------- 1 | # theme.toml template for a Hugo theme 2 | # See https://github.com/gohugoio/hugoThemes#themetoml for an example 3 | 4 | name = "Creativebulma" 5 | license = "MIT" 6 | licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE" 7 | description = "" 8 | homepage = "http://example.com/" 9 | tags = [] 10 | features = [] 11 | min_version = "0.41" 12 | 13 | [author] 14 | name = "" 15 | homepage = "" 16 | 17 | # If porting an existing theme 18 | [original] 19 | name = "" 20 | homepage = "" 21 | repo = "" 22 | -------------------------------------------------------------------------------- /docs/tags/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tags on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/tags/ 6 | Recent content in Tags on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/button.html: -------------------------------------------------------------------------------- 1 | {{ $_hugo_config := `{ "version": 1 }` }} 2 | {{ $ref := "" }} 3 | {{ $target := "" }} 4 | {{ with .Get "href" }} 5 | {{ $ref = . }} 6 | {{ $target = "_blank" }} 7 | {{ end }} 8 | {{ with .Get "relref" }} 9 | {{ $ref = relref $ . }} 10 | {{ end }} 11 | 12 | {{ $icon := .Get "icon" }} 13 | {{ if ($icon) }} 14 | 15 | {{ end }} 16 | {{ .Inner }} 17 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/variables.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ range .Site.Data.variables }} 11 | 12 | 13 | 14 | 15 | 16 | {{ end }} 17 | 18 |
Variable nameDescriptionDefault value
{{ .name }}{{ .description | $.Page.RenderString }}{{ .value }}
-------------------------------------------------------------------------------- /docs/categories/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Categories on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/categories/ 6 | Recent content in Categories on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "jest": true 7 | }, 8 | "globals": { 9 | "ENV": true, 10 | "page": true, 11 | "browser": true, 12 | "context": true, 13 | "jestPuppeteer": true 14 | }, 15 | "extends": "eslint:recommended", 16 | "parserOptions": { 17 | "sourceType": "module", 18 | "ecmaVersion": 9, 19 | "ecmaFeatures": { 20 | "experimentalObjectRestSpread": true 21 | } 22 | }, 23 | "rules": { 24 | "indent": [ 25 | "error", 26 | 2, 27 | "tab" 28 | ], 29 | "linebreak-style": [ 30 | "error", 31 | "unix" 32 | ], 33 | "quotes": [ 34 | "error", 35 | "single" 36 | ], 37 | "semi": [ 38 | "error", 39 | "always" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/table.html: -------------------------------------------------------------------------------- 1 | {{ $source := index .Site.Data (.Get "source") }} 2 | {{ $headers := $source.headers }} 3 | {{ $body := $source.body }} 4 | 5 | 6 | 7 | {{ range $headers }} 8 | 9 | {{ end }} 10 | 11 | 12 | 13 | {{ range $body }} 14 | 15 | 16 | 17 | 18 | 19 | {{ end }} 20 | 21 |
{{ .name }}
{{ .name }}{{ .description | $.Page.RenderString }}{{ highlight .example "javascript" "" }}
-------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@babel/env'], 4 | ['minify', { 5 | 'builtIns': false, 6 | 'keepClassName': true, 7 | 'keepFnName': true 8 | }] 9 | ], 10 | plugins: [ 11 | '@babel/plugin-transform-runtime', 12 | '@babel/plugin-proposal-class-properties', 13 | ['@babel/plugin-proposal-decorators', { 14 | 'legacy': true 15 | }], 16 | '@babel/plugin-transform-async-to-generator', 17 | '@babel/plugin-transform-arrow-functions', 18 | '@babel/plugin-transform-block-scoping', 19 | '@babel/plugin-transform-destructuring', 20 | '@babel/plugin-transform-modules-commonjs', 21 | '@babel/plugin-transform-parameters', 22 | '@babel/plugin-proposal-object-rest-spread', 23 | '@babel/plugin-proposal-export-default-from' 24 | ] 25 | }; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const entry = require('webpack-glob-entry'); 2 | const path = require('path'); 3 | const parsePath = require('parse-filepath'); 4 | const package = require('./package.json'); 5 | 6 | distPath = parsePath(package.script); 7 | 8 | module.exports = { 9 | mode: 'production', 10 | entry: entry('./src/js/index.js'), 11 | output: { 12 | filename: distPath.basename ? distPath.basename : '[name].js', 13 | path: path.resolve(__dirname, 'dist'), 14 | library: package.library, 15 | libraryTarget: 'umd', 16 | libraryExport: 'default', 17 | umdNamedDefine: true 18 | }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.js$/, 23 | exclude: /(node_modules|bower_components)/, 24 | loader: 'babel-loader' 25 | } 26 | ] 27 | }, 28 | optimization: { 29 | minimize: false 30 | } 31 | }; -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{ range .Site.Data.options }} 12 | 13 | 14 | 15 | {{ if .type }} 16 | 17 | {{ end }} 18 | 19 | 20 | {{ end }} 21 | 22 |
Option nameDescriptionTypeDefault value
{{ .name }}{{ .description | $.Page.RenderString }}{{ .type | $.Page.RenderString }}{{ .value }}
-------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/tabs.html: -------------------------------------------------------------------------------- 1 |
2 | 21 |
22 |
23 | {{ .Inner }} 24 |
-------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ partial "head" . }} 2 |
3 | 4 |
5 | 6 | 7 | 8 |
9 |
10 | 13 |
14 | {{ partial "navbar" . }} 15 | 16 |
17 |
18 | {{ .Content }} 19 |
20 |
21 |
22 |
23 |
24 | {{ partial "footer" . }} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "head" . }} 2 |
3 | 4 |
5 | 6 | 7 | 8 |
9 |
10 | 13 |
14 | {{ partial "navbar" . }} 15 | 16 |
17 |
18 | {{ .Content }} 19 |
20 |
21 |
22 |
23 |
24 | 25 | {{ partial "footer" . }} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ block "meta_tags" . }}{{end}} 11 | 12 | {{ block "title" . }}{{ .Title }} - {{ .Site.Title }}{{ end }} 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{ block "header_css" . }}{{ end }} 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/docs/layouts/partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ block "meta_tags" . }}{{end}} 11 | 12 | {{ block "title" . }}{{ .Title }} - {{ .Site.Title }}{{ end }} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{ block "header_css" . }}{{ end }} 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 404 Page not found - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 |
24 |

Page not found

25 |

26 | 27 |

28 |
29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/docs/content/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction" 3 | date: "2020-03-21" 4 | menu: "main" 5 | weight: 1 6 | draft: false 7 | --- 8 | 9 | # Introduction 10 | ## What is BulmaTagsInput 11 | 12 | BulmaTagsInput is a {{% link text="Bulma" href="https://bulma.io" target="_blank" %}} extension which brings **a full-featured user interface for managing tags supporting autocomplete** to your project. 13 | 14 | ## License 15 | BulmaTagsInput is © 2020 by [CreativeBulma](https://github.com/CreativeBulma). 16 | 17 | BulmaTagsInput is distributed under [MIT](https://github.com/CreativeBulma/bulma-tagsinput/blob/master/LICENSE) license. 18 | 19 | ## Contributing 20 | 21 | **Contribution are welcome!** 22 | 23 | You found a bug, a typo issue ? Feel free to create a PR on the [github repository](https://github.com/CreativeBulma/bulma-tagsinput/) of this project. 24 | 25 | When contributing to this project, please first discuss the change you wish to make via issue on the [github repository](https://github.com/CreativeBulma/bulma-tagsinput//issues), email, or any other method with the owners of this project before making a change. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 CreativeBulma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ block "meta_tags" . }}{{end}} 11 | 12 | {{ block "title" . }}{{ .Title }} - {{ .Site.Title }}{{ end }} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 |
24 |

Page not found

25 |

26 | 27 |

28 |
29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 YOUR_NAME_HERE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/preview.html: -------------------------------------------------------------------------------- 1 | {{ $previewID := $.Get "id" }} 2 | {{ $lang := "html" }} 3 | {{ with .Get "lang" }} 4 | {{ $lang = . }} 5 | {{ end }} 6 | {{ $options := "" }} 7 | {{ with .Get "options" }} 8 | {{ $options = . }} 9 | {{ end }} 10 |
11 |
12 | 22 |
23 |
24 |
25 | {{ $.Inner }} 26 |
27 |
28 | {{ highlight $.Inner $lang $options }} 29 |
30 |
31 |
-------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/tag.html: -------------------------------------------------------------------------------- 1 | {{ $type := .Get 0 }} 2 | {{ $text := .Get 1 }} 3 | {{ with eq $type "added" }} 4 | {{ $type }} 5 | {{ end }} 6 | {{ with eq $type "changed" }} 7 | {{ $type }} 8 | {{ end }} 9 | {{ with eq $type "fixed" }} 10 | {{ $type }} 11 | {{ end }} 12 | {{ with eq $type "performance" }} 13 | {{ $type }} 14 | {{ end }} 15 | {{ with eq $type "security" }} 16 | {{ $type }} 17 | {{ end }} 18 | {{ with eq $type "removed" }} 19 | {{ $type }} 20 | {{ end }} 21 | {{ with eq $type "deprecated" }} 22 | {{ $type }} 23 | {{ end }} 24 | {{ with eq $type "info" }} 25 | {{ $text }} 26 | {{ end }} 27 | {{ with eq $type "success" }} 28 | {{ $text }} 29 | {{ end }} 30 | {{ with eq $type "warning" }} 31 | {{ $text }} 32 | {{ end }} 33 | {{ with eq $type "danger" }} 34 | {{ $text }} 35 | {{ end }} -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/docs/content/how-to/customize.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Customize" 3 | date: "2020-03-21" 4 | menu: 5 | main: 6 | parent: 'how-to' 7 | weight: 1 8 | weight: 1 9 | draft: false 10 | --- 11 | 12 | # How-To 13 | ## Customize 14 | This component has been designed to be easily customizable. 15 | 16 | There is 2 ways to customize it, depending on the way you integrate this component into your project. 17 | 18 | ## Sass 19 | If you use the Sass source into your project, all you have to do is to customize variables **before** importing the component. 20 | ```sass 21 | $tagsinput-selected-background-color: $dark 22 | 23 | @import '@creativebulma/bulma-tagsinput' 24 | ``` 25 | 26 | ### Variables 27 | {{< variables >}} 28 | 29 | ## CSS 30 | If you uses the CSS version you have to customize Sass source files then rebuild the CSS file. 31 | 32 | ### First, let's install some packages! 33 | 34 | ```shell 35 | npm install 36 | ``` 37 | This command will install all development required package. 38 | 39 | ### Customize 40 | Customize Sass variables defined within `src/sass/index.sass` file. 41 | 42 | ### Build 43 | You can build CSS files by launching the build process with the command: 44 | ```shell 45 | npm run build 46 | ``` 47 | Styles are built using `node-sass` from `src/sass` directory and minify them. 48 | Built files will be copied into `/dist` directory (can be customized within package.json). 49 | -------------------------------------------------------------------------------- /src/js/utils/type.js: -------------------------------------------------------------------------------- 1 | export const isFunction = unknown => typeof unknown === 'function'; 2 | export const isString = unknown => (typeof unknown === 'string' || ((!!unknown && typeof unknown === 'object') && Object.prototype.toString.call(unknown) === '[object String]')); 3 | export const isObject = unknown => ((typeof unknown === 'function' || (typeof unknown === 'object' && !!unknown)) && !Array.isArray(unknown)); 4 | // Returns true if the value has a "then" function. Adapted from 5 | // https://github.com/graphql/graphql-js/blob/499a75939f70c4863d44149371d6a99d57ff7c35/src/jsutils/isPromise.js 6 | export const isPromise = value => Boolean(value && typeof value.then === 'function'); 7 | 8 | export const isNode = unknown => { 9 | try { 10 | Node.prototype.cloneNode.call(unknown, false); 11 | return true; 12 | } catch (err) { 13 | return false; 14 | } 15 | }; 16 | 17 | /** 18 | * Convert String (false,False,True,true,no,yes,0,1) to real Boolean 19 | * @param {String} val 20 | */ 21 | export const BooleanParse = function (val) { 22 | const falsy = /^(?:f(?:alse)?|no?|0+)$/i; 23 | 24 | return !falsy.test(val) && !!val; 25 | }; 26 | 27 | /** 28 | * Check if given query selector is valid 29 | * @param {String} selector 30 | */ 31 | export const isSelectorValid = selector => { 32 | const queryCheck = s => document.createDocumentFragment().querySelector(s) 33 | try { 34 | queryCheck(selector); 35 | } catch { 36 | return false; 37 | } 38 | 39 | return true; 40 | } -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/partials/menu.html: -------------------------------------------------------------------------------- 1 | 2 | {{ .Site.Title }} 3 | docs 4 | 5 | -------------------------------------------------------------------------------- /docs/how-to/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | How-tos on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/ 6 | Recent content in How-tos on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | Sat, 21 Mar 2020 00:00:00 +0000 10 | 11 | 12 | 13 | 14 | 15 | Customize 16 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/customize/ 17 | Sat, 21 Mar 2020 00:00:00 +0000 18 | 19 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/customize/ 20 | How-To Customize This component has been designed to be easily customizable. 21 | There is 2 ways to customize it, depending on the way you integrate this component into your project. 22 | Sass If you use the Sass source into your project, all you have to do is to customize variables before importing the component. 23 | $tagsinput-selected-background-color: $dark @import &#39;@creativebulma/bulma-tagsinput&#39; Variables Variable name Description Default value $tagsinput-selected-background-color $primary $tagsinput-duplicate-animation blinker . 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/js/defaultOptions.js: -------------------------------------------------------------------------------- 1 | import tag from "./templates/tag"; 2 | 3 | const defaultOptions = { 4 | allowDuplicates: false, // Are duplicate tags allowed ? 5 | caseSensitive: true, // Is duplicate tags identification case sensitive ? 6 | clearSelectionOnTyping: false, // Should selected tag be cleared when typing a new input ? 7 | closeDropdownOnItemSelect: true, // Should dropdown be closed once an item has been clicked ? 8 | delimiter: ',', // Multiple tags delimiter 9 | freeInput: true, // Should user be able to input new tag manually ? 10 | highlightDuplicate: true, // Should we temporarly highlight identified duplicate tags ? 11 | highlightMatchesString: true, // Should we highlight identified matches strings when searching ? 12 | itemValue: undefined, // What is the object property to use as value when we work with Object tags ? 13 | itemText: undefined, // What is the object property to use as text when we work with Object tags ? 14 | maxTags: undefined, // Maximum number of tags allowed 15 | maxChars: undefined, // Maximum of characters allowed for a single tag 16 | minChars: 1, // Minimum of characters before processing a new tag 17 | noResultsLabel: 'No results found', // Customize the dropdown placecholer when no results found 18 | placeholder: '', // Customize the input placholder 19 | removable: true, // Are tags removable ? 20 | searchMinChars: 1, // How many characters should we enter before starting dynamic search ? 21 | searchOn: 'text', // On what dropdown item data do we search the entered value : 'value' or 'text' ? 22 | selectable: true, // Are tags selectable ? 23 | source: undefined, // Array/Function/Promise to get external data 24 | tagClass: 'is-rounded', // Customize tags style by passing classes - They will be added to the tag element 25 | trim: true // Should we trim value before processing them ? 26 | } 27 | 28 | export default defaultOptions; 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :exclamation::exclamation::exclamation: Looking for new Maintainer :exclamation::exclamation::exclamation: 2 | As you may have noticed, this package has not been updated for some time. I'm sorry, but unfortunately I'm not able to continue to maintain it, so I'm looking for someone who would like to take it over and maintain it. **If you are interested, open an issue to request ownership transfer.** 3 | 4 | # Introduction 5 | This components has been developped as a [Bulma](https://bulma.io) extension and brings **a full-featured user interface for managing tags supporting autocomplete** to your project. 6 | 7 | [![npm](https://img.shields.io/npm/v/@creativebulma/bulma-tagsinput.svg)](https://www.npmjs.com/package/@creativebulma/bulma-tagsinput) 8 | [![npm](https://img.shields.io/npm/dm/@creativebulma/bulma-tagsinput.svg)](https://www.npmjs.com/package/@creativebulma/bulma-tagsinput) 9 | [![](https://data.jsdelivr.com/v1/package/npm/@creativebulma/bulma-tagsinput/badge)](https://www.jsdelivr.com/package/npm/@creativebulma/bulma-tagsinput) 10 | 11 | --- 12 | 13 | ## Prerequisites 14 | This component extends [Bulma CSS Framework](https://bulma.io) and requires it to work. 15 | 16 | ## Get Started 17 | ```shell 18 | npm i -D @creativebulma/bulma-tagsinput 19 | ``` 20 | Full installation steps can be found here: [installation steps](https://bulma-tagsinput.netlify.app/get-started) 21 | 22 | ## Documentation & Demo 23 | Full documentation and demo are available [here](https://bulma-tagsinput.netlify.app) 24 | 25 | ## About the project 26 | BulmaTagsInput is © 2020 by [CreativeBulma](https://github.com/CreativeBulma). 27 | 28 | ## License 29 | BulmaTagsInput is distributed under [MIT](https://github.com/CreativeBulma/bulma-tagsinput/blob/master/LICENSE) license. 30 | 31 | ## Contributing 32 | **Contribution are welcome!** 33 | You found a bug, a typo issue ? Feel free to create a PR on the [github repository](https://github.com/CreativeBulma/bulma-tagsinput/) of this project. 34 | 35 | When contributing to this project, please first discuss the change you wish to make via issue on the [github repository](https://github.com/CreativeBulma/bulma-tagsinput/issues), email, or any other method with the owners of this project before making a change. 36 | -------------------------------------------------------------------------------- /docs/release/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Releases on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/release/ 6 | Recent content in Releases on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | Fri, 15 May 2020 10:46:47 +0200 10 | 11 | 12 | 13 | 14 | 15 | (2020-05-15) 16 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.2/ 17 | Fri, 15 May 2020 10:46:47 +0200 18 | 19 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.2/ 20 | Important fixes for select based TagsInput 21 | fixed Multiple pre-selected options not working fixed Tags still removable when select is disabled 22 | 23 | 24 | 25 | (2020-05-07) 26 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.1/ 27 | Thu, 07 May 2020 10:46:47 +0200 28 | 29 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.1/ 30 | Important fix for Form data 31 | fixed Duplicate form data when submitting 32 | 33 | 34 | 35 | (2020-05-02) 36 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1/ 37 | Sat, 02 May 2020 10:46:47 +0200 38 | 39 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1/ 40 | First working version 41 | added Works with Input, Select, Multiple Select elements added Customize behavior with lots of options added Events API added External data source management added Filtering/Search 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/layouts/shortcodes/api.html: -------------------------------------------------------------------------------- 1 | 2 | {{ range .Site.Data.api }} 3 | {{ if isset . "type" }} 4 |
5 | {{ .name }} 6 | : 7 | {{ .type }} 8 | 9 | {{ if (eq .scope "constructor") }} 10 |
{{ .scope }}
11 | {{ end }} 12 | {{ if (eq .scope "private") }} 13 |
{{ .scope }}
14 | {{ end }} 15 | {{ if (eq .scope "public") }} 16 |
{{ .scope }}
17 | {{ end }} 18 |
19 |
20 | {{ else }} 21 |
22 | {{ .name }} 23 | 24 | {{ if (eq .scope "constructor") }} 25 |
{{ .scope }}
26 | {{ end }} 27 | {{ if (eq .scope "private") }} 28 |
{{ .scope }}
29 | {{ end }} 30 | {{ if (eq .scope "public") }} 31 |
{{ .scope }}
32 | {{ end }} 33 |
34 |
35 | {{ end }} 36 | {{ if isset . "description" }} 37 |

{{ .description | $.Page.RenderString }}

38 | {{ end }} 39 | {{ if isset . "parameters" }} 40 |
Parameters
41 | {{ range .parameters }} 42 | 63 |
{{ .description | $.Page.RenderString }}
64 | {{ end }} 65 | {{ end }} 66 | {{ if isset . "example" }} 67 |
Example
68 | {{ highlight .example "javascript" "" }} 69 | {{ end }} 70 |
71 | {{ end }} -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.2/ 7 | 2020-05-15T10:46:47+02:00 8 | 9 | 10 | 11 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.1/ 12 | 2020-05-07T10:46:47+02:00 13 | 14 | 15 | 16 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1/ 17 | 2020-05-02T10:46:47+02:00 18 | 19 | 20 | 21 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/customize/ 22 | 2020-03-21T00:00:00+00:00 23 | 24 | 25 | 26 | https://demo.creativebulma.net/components/tagsinput/1.0/ 27 | 2020-03-21T00:00:00+00:00 28 | 29 | 30 | 31 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 32 | 2020-03-21T00:00:00+00:00 33 | 34 | 35 | 36 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/usage/ 37 | 2020-03-21T00:00:00+00:00 38 | 39 | 40 | 41 | https://demo.creativebulma.net/components/tagsinput/1.0/changelog/ 42 | 2020-05-02T00:00:00+00:00 43 | 44 | 45 | 46 | https://demo.creativebulma.net/components/tagsinput/1.0/release/ 47 | 2020-05-15T10:46:47+02:00 48 | 49 | 50 | 51 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 52 | 2020-03-21T00:00:00+00:00 53 | 54 | 55 | 56 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/ 57 | 2020-03-21T00:00:00+00:00 58 | 59 | 60 | 61 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/javascript-api/ 62 | 2020-03-21T00:00:00+00:00 63 | 64 | 65 | 66 | https://demo.creativebulma.net/components/tagsinput/1.0/categories/ 67 | 68 | 69 | 70 | https://demo.creativebulma.net/components/tagsinput/1.0/tags/ 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/docs/content/get-started/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Installation" 3 | date: "2020-03-21" 4 | menu: 5 | main: 6 | parent: 'get-started' 7 | weight: 2 8 | url: /get-started/ 9 | weight: 2 10 | draft: false 11 | --- 12 | 13 | {{% notification warning %}}This component extends Bulma CSS Framework, so you need to have Bulma installed to use it.{{% /notification %}} 14 | 15 | ## Installation 16 | ### First, let's install the component! 17 | There are several ways to get started with BulmaTagsInput. 18 | {{< tabs tabTotal="3" tabID="install" tabName1="1. NPM" tabName2="2. CDN" tabName3="3. Github" >}} 19 | {{< tab tabNum="1" >}} 20 | Use npm to install the `bulma-tagsinput` package **recommended** 21 | ```shell 22 | npm install @creativebulma/bulma-tagsinput 23 | ``` 24 | {{< /tab >}} 25 | 26 | {{< tab tabNum="2" >}} 27 | Use the [jsDelivr](https://jsdelivr.com) CDN to link to the BulmaTagsInput stylesheet 28 | ```html 29 | https://www.jsdelivr.com/package/npm/@creativebulma/bulma-tagsinput 30 | ``` 31 | {{< /tab >}} 32 | 33 | {{< tab tabNum="3" >}} 34 | Use the GitHub repository to get the latest development version. 35 | 36 | Download from the repository [https://github.com/CreativeBulma/bulma-tagsinput/tree/master/dist/](https://github.com/CreativeBulma/bulma-tagsinput/tree/master/dist/) 37 | {{< /tab >}} 38 | {{< /tabs >}} 39 | 40 | ### Integrate styles 41 | {{< tabs tabTotal="2" tabID="import-style" tabName1="1. Browser" tabName2="2. Sass" >}} 42 | {{< tab tabNum="1" >}} 43 | ```html 44 | 45 | ``` 46 | {{< /tab >}} 47 | 48 | {{< tab tabNum="2" >}} 49 | Open you application's main sass file and add the following lines: 50 | ```sass 51 | // Import Bulma first 52 | @import 'bulma'; 53 | 54 | // Import BulmaTagsInput main Sass File 55 | @import '@creativebulma/bulma-tagsinput/src/sass/index'; 56 | ``` 57 | {{< /tab >}} 58 | {{< /tabs >}} 59 | 60 | ### Integrate the JavaScript 61 | {{< tabs tabTotal="2" tabID="import-js" tabName1="1. Browser" tabName2="2. ES6" >}} 62 | {{< tab tabNum="1" >}} 63 | ```html 64 | 65 | ``` 66 | {{< /tab >}} 67 | 68 | {{< tab tabNum="2" >}} 69 | ```javascript 70 | import BulmaTagsInput from '@creativebulma/bulma-tagsinput'; 71 | ``` 72 | {{< /tab >}} 73 | {{< /tabs >}} 74 | 75 | See [JavaScript API]({{< relref "/get-started/javascript-api" >}}) documentation to find out how to work with the component in Javascript. 76 | 77 | ## Framework Integration 78 | {{< tabs tabTotal="2" tabID="framework-integration" tabName1="1. ReactJS" tabName2="2. VueJS" >}} 79 | {{< tab tabNum="1" >}} 80 | See our [ReactJS integration](https://codepen.io/CreativeBulma/pen/PoPJVQx) example on CodePen 81 | {{< /tab >}} 82 | 83 | {{< tab tabNum="2" >}} 84 | See our [VueJS integration](https://codepen.io/CreativeBulma/pen/pojWGpo) example on CodePen 85 | {{< /tab >}} 86 | {{< /tabs >}} 87 | 88 | # You're ready to [use BulmaTagsInput]({{< relref "/get-started/usage" >}}) ! -------------------------------------------------------------------------------- /src/js/utils/dom.js: -------------------------------------------------------------------------------- 1 | import { isFunction, isNode, isString } from './type'; 2 | 3 | /** 4 | * querySelector under steroid 5 | * Can use as selector: 6 | * - function 7 | * - DOM Node 8 | * - String 9 | * @param {String|Node|Function} selector 10 | * @param {Node|undefined} node 11 | */ 12 | export const querySelector = (selector, node) => { 13 | if (isFunction(selector)) { 14 | return selector(node); 15 | } 16 | 17 | if (isNode(selector)) { 18 | return selector; 19 | } 20 | 21 | if (isString(selector)) { 22 | if (!node || !isNode(node) || node.nodeType !== 1) { 23 | node = document; 24 | } 25 | 26 | return node.querySelector(selector); 27 | } 28 | 29 | if (Array.isArray(selector) || (typeof NodeList !== 'undefined' && NodeList.prototype.isPrototypeOf(selector))) { 30 | return selector[0]; 31 | } 32 | } 33 | 34 | /** 35 | * querySelectorAll under steroid 36 | * Can use as selector: 37 | * - function 38 | * - DOM Node 39 | * - String 40 | * @param {String|Node|Function} selector 41 | * @param {Node|undefined} node 42 | */ 43 | export const querySelectorAll = (selector, node) => { 44 | if (isFunction(selector)) { 45 | return selector(node); 46 | } 47 | 48 | if (isNode(selector)) { 49 | return [selector]; 50 | } 51 | 52 | if (isString(selector)) { 53 | if (!node || !isNode(node) || node.nodeType !== 1) { 54 | node = document; 55 | } 56 | 57 | return node.querySelectorAll(selector); 58 | } 59 | 60 | if (typeof NodeList !== 'undefined' && NodeList.prototype.isPrototypeOf(selector)) { 61 | return selector; 62 | } else { 63 | return []; 64 | } 65 | }; 66 | 67 | // Convert dataset into Object 68 | export const optionsFromDataset = (node, defaultOptions = {}) => { 69 | if (isNode(node)) { 70 | return node.dataset ? Object.keys(node.dataset) 71 | .filter(key => Object.keys(defaultOptions).includes(key)) 72 | .reduce((obj, key) => { 73 | return { 74 | ...obj, 75 | [key]: node.dataset[key] 76 | }; 77 | }, {}) : {}; 78 | } else { 79 | return {}; 80 | } 81 | }; 82 | 83 | /** 84 | * Copy HTML attributes from a source element to a target element 85 | * @param {Node} target 86 | * @param {Node} source 87 | * @param {String} except list of attributes to skip (separated by space) 88 | */ 89 | export const cloneAttributes = (target, source, except = null) => { 90 | if (except !== null) { 91 | except = except.split(' '); 92 | } 93 | 94 | [...source.attributes].forEach(attr => { 95 | if (!except.includes(attr.nodeName)) { 96 | target.setAttribute(attr.nodeName === "id" ? 'data-id' : attr.nodeName, attr.nodeValue); 97 | } 98 | }); 99 | }; 100 | 101 | /** 102 | * Escapes string for insertion into HTML, replacing special characters with HTML 103 | * entities. 104 | * @param {String} string 105 | */ 106 | export const escape = (string) => { 107 | return isString(string) ? 108 | string.replace(/(['"<>])/g, (char) => { 109 | return { 110 | '<': "<", 111 | '>': ">", 112 | '"': """, 113 | "'": "'" 114 | }[char]; 115 | }) 116 | : string; 117 | }; 118 | -------------------------------------------------------------------------------- /src/js/utils/component.js: -------------------------------------------------------------------------------- 1 | import EventEmitter from './events'; 2 | import { optionsFromDataset, querySelectorAll, querySelector } from './dom'; 3 | import uuid from './uuid'; 4 | 5 | export default class Component extends EventEmitter { 6 | constructor(element, options = {}, defaultOptions = {}) { 7 | super(); 8 | 9 | this.element = querySelector(element, document); 10 | 11 | // An invalid selector or non-DOM node has been provided. 12 | if (!this.element) { 13 | throw new Error(`An invalid selector or non-DOM node has been provided for ${this.constructor.name}.`); 14 | } 15 | 16 | this.element[this.constructor.name] = this.constructor._interface.bind(this); 17 | this.element[this.constructor.name].Constructor = this.constructor.name; 18 | this.id = uuid(this.constructor.name + '-'); 19 | 20 | this.options = { 21 | ...defaultOptions, 22 | ...options, 23 | ...optionsFromDataset(this.element, defaultOptions) // Use Element dataset values to override options 24 | }; 25 | } 26 | 27 | /** 28 | * Initiate all DOM element corresponding to selector 29 | * @method 30 | * @return {Array} Array of all Plugin instances 31 | */ 32 | static attach(selector = null, options = {}, node = null) { 33 | let instances = new Array(); 34 | 35 | if (selector !== null) { 36 | querySelectorAll(selector, node).forEach(element => { 37 | // Check if plugin has already been instantiated for element 38 | if (typeof element[this.name] === 'undefined') { // If no then instantiate it and register it in element 39 | instances.push(new this(element, { 40 | selector: selector, 41 | ...options 42 | })); 43 | } else { // If Yes then return the existing instance 44 | instances.push(element[this.name]); 45 | } 46 | }); 47 | 48 | if (typeof window[this.name] === 'undefined') { 49 | window[this.name] = { 50 | 'observers': [] 51 | }; 52 | } 53 | 54 | if (window[this.name]['observers'] && !window[this.name]['observers'].includes(selector)) { 55 | this.observeDom(selector, options); 56 | 57 | window[this.name]['observers'].push(selector); 58 | } 59 | } 60 | 61 | return instances; 62 | } 63 | 64 | /** 65 | * Observe DOM mutations to automatically initialize plugin on new elements when added to the DOM 66 | * 67 | * @param {string} selector 68 | * @param {Object} options 69 | */ 70 | static observeDom(selector, options) { 71 | const observer = new MutationObserver(mutations => { 72 | mutations.forEach(mutation => { 73 | for (let i = 0; i < mutation.addedNodes.length; i++) { 74 | if (typeof window[this.name] !== 'undefined') { 75 | this.attach(selector, options, mutation.addedNodes[i]); 76 | } 77 | } 78 | }); 79 | }); 80 | 81 | if (typeof document !== 'undefined') { 82 | observer.observe(document, { 83 | childList: true, 84 | subtree: true 85 | }); 86 | } 87 | } 88 | 89 | static _interface(name = null, options = {}) { 90 | if (typeof name === 'string') { 91 | if (typeof this[name] === 'undefined') { 92 | throw new TypeError(`No method named "${name}"`); 93 | } 94 | 95 | return this[name](options); 96 | } 97 | 98 | return this; 99 | } 100 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@creativebulma/bulma-tagsinput", 3 | "description": "A full-featured user interface for managing tags with Bulma supporting autocomplete.", 4 | "version": "1.0.3", 5 | "homepage": "https://github.com/CreativeBulma/bulma-tagsinput", 6 | "main": "./dist/js/bulma-tagsinput.js", 7 | "module": "./src/js/index.js", 8 | "style": "./dist/css/bulma-tagsinput.css", 9 | "script": "./dist/js/bulma-tagsinput.js", 10 | "sass": "./src/sass/index.sass", 11 | "library": "BulmaTagsInput", 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/CreativeBulma/bulma-tagsinput.git" 15 | }, 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/CreativeBulma/bulma-tagsinput/issues" 19 | }, 20 | "keywords": [ 21 | "tags", 22 | "input", 23 | "tagsinput", 24 | "autocomplete", 25 | "autocompletion", 26 | "typehead", 27 | "ui", 28 | "component", 29 | "extension", 30 | "html", 31 | "html5", 32 | "css3", 33 | "sass", 34 | "bulma", 35 | "bulmaio", 36 | "bulma.io" 37 | ], 38 | "devDependencies": { 39 | "@babel/core": "^7.8.3", 40 | "@babel/plugin-proposal-class-properties": "^7.8.3", 41 | "@babel/plugin-proposal-decorators": "^7.8.3", 42 | "@babel/plugin-proposal-export-default-from": "^7.8.3", 43 | "@babel/plugin-proposal-object-rest-spread": "^7.8.3", 44 | "@babel/plugin-transform-arrow-functions": "^7.8.3", 45 | "@babel/plugin-transform-async-to-generator": "^7.8.3", 46 | "@babel/plugin-transform-block-scoping": "^7.8.3", 47 | "@babel/plugin-transform-destructuring": "^7.8.3", 48 | "@babel/plugin-transform-modules-commonjs": "^7.8.3", 49 | "@babel/plugin-transform-parameters": "^7.8.3", 50 | "@babel/plugin-transform-runtime": "^7.8.3", 51 | "@babel/preset-env": "^7.8.3", 52 | "@babel/runtime": "^7.8.3", 53 | "autoprefixer": "^9.7.4", 54 | "babel-loader": "^8.0.6", 55 | "babel-plugin-add-module-exports": "^1.0.2", 56 | "babel-preset-minify": "^0.5.1", 57 | "bulma": "^0.8", 58 | "eslint": "^6.8.0", 59 | "eslint-config-prettier": "^6.9.0", 60 | "fs": "0.0.1-security", 61 | "gulp": "^4.0.2", 62 | "gulp-cache-bust": "^1.4.1", 63 | "gulp-clean-dir": "^1.0.2", 64 | "gulp-cleancss": "^0.2.2", 65 | "gulp-concat": "^2.6.1", 66 | "gulp-cssnano": "^2.1.3", 67 | "gulp-header": "^2.0.9", 68 | "gulp-if": "^3.0.0", 69 | "gulp-nop": "0.0.3", 70 | "gulp-postcss": "^8.0.0", 71 | "gulp-rename": "^2.0.0", 72 | "gulp-run": "^1.7.1", 73 | "gulp-sass": "^4.0.2", 74 | "gulp-shell": "^0.8.0", 75 | "gulp-svgmin": "^2.2.0", 76 | "gulp-terser": "^1.2.0", 77 | "hugo-bin": "^0.55.0", 78 | "internal-ip": "^6.0.0", 79 | "parse-filepath": "^1.0.2", 80 | "path": "^0.12.7", 81 | "webpack": "^4.42.0", 82 | "webpack-glob-entry": "^2.1.1", 83 | "webpack-stream": "^5.2.1" 84 | }, 85 | "scripts": { 86 | "build": "gulp", 87 | "build:styles": "gulp build:styles", 88 | "demo": "gulp demo", 89 | "demo:build": "gulp demo:build", 90 | "demo:serve": "gulp demo:serve", 91 | "doc": "gulp doc", 92 | "doc:build": "gulp doc:build", 93 | "doc:serve": "gulp doc:serve", 94 | "optimize": "gulp optimize", 95 | "start": "gulp demo:serve" 96 | }, 97 | "files": [ 98 | "dist", 99 | "src", 100 | "LICENSE", 101 | "README.md" 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /docs/js/docs.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | // clipboard 3 | var clipInit = false; 4 | var codes = document.querySelectorAll('code') || []; 5 | codes.forEach(function(code) { 6 | var text = code.innerHTML; 7 | 8 | if (text.length > 5) { 9 | if (!clipInit) { 10 | var text, clip = new ClipboardJS('.copy-to-clipboard', { 11 | text: function(trigger) { 12 | text = trigger.previousSibling.innerHTML; 13 | return text.replace(/^\$\s/gm, ''); 14 | } 15 | }); 16 | 17 | var inPre; 18 | clip.on('success', function(e) { 19 | e.clearSelection(); 20 | inPre = e.trigger.parentNode.tagName == 'PRE'; 21 | e.trigger.setAttribute('aria-label', 'Copied to clipboard!'); 22 | e.trigger.classList.add('tooltipped'); 23 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 24 | }); 25 | 26 | clip.on('error', function(e) { 27 | inPre = e.trigger.parentNode.tagName == 'PRE'; 28 | e.trigger.setAttribute('aria-label', fallbackMessage(e.action)); 29 | e.trigger.classList.add('tooltipped'); 30 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 31 | document.addEventListener('copy', function(){ 32 | e.trigger.setAttribute('aria-label', 'Copied to clipboard!'); 33 | e.trigger.classList.add('tooltipped'); 34 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 35 | }); 36 | }); 37 | 38 | clipInit = true; 39 | } 40 | 41 | var copyNode = document.createElement('div'); 42 | copyNode.classList.add('copy-to-clipboard'); 43 | copyNode.setAttribute('title', 'Copy to clipboard'); 44 | 45 | code.after(copyNode); 46 | code.nextSibling.addEventListener('mouseleave', function() { 47 | this.setAttribute('aria-label', null); 48 | this.classList.remove('tooltipped'); 49 | this.classList.remove('tooltipped-s'); 50 | this.classList.remove('tooltipped-w'); 51 | }); 52 | } 53 | }); 54 | 55 | const tabs = document.querySelectorAll('[data-toggle="tab"]') || []; 56 | tabs.forEach(function(tab) { 57 | tab.addEventListener('click', function(e) { 58 | e.preventDefault(); 59 | e.stopPropagation(); 60 | 61 | const tabPane = document.querySelector(e.currentTarget.dataset.target); 62 | 63 | const activeTab = e.currentTarget.closest('.tabs ul').querySelector('li.is-active'); 64 | const activeTabPane = document.querySelector(activeTab.dataset.target); 65 | if (activeTab && !activeTab.isSameNode(e.currentTarget)) { 66 | activeTab.classList.remove('is-active'); 67 | if (activeTabPane) { 68 | activeTabPane.classList.remove('is-active'); 69 | } 70 | 71 | } 72 | 73 | e.currentTarget.classList.add('is-active'); 74 | if (tabPane) { 75 | tabPane.classList.add('is-active'); 76 | } 77 | }); 78 | }); 79 | }, false); -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/static/js/docs.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | // clipboard 3 | var clipInit = false; 4 | var codes = document.querySelectorAll('code') || []; 5 | codes.forEach(function(code) { 6 | var text = code.innerHTML; 7 | 8 | if (text.length > 5) { 9 | if (!clipInit) { 10 | var text, clip = new ClipboardJS('.copy-to-clipboard', { 11 | text: function(trigger) { 12 | text = trigger.previousSibling.innerHTML; 13 | return text.replace(/^\$\s/gm, ''); 14 | } 15 | }); 16 | 17 | var inPre; 18 | clip.on('success', function(e) { 19 | e.clearSelection(); 20 | inPre = e.trigger.parentNode.tagName == 'PRE'; 21 | e.trigger.setAttribute('aria-label', 'Copied to clipboard!'); 22 | e.trigger.classList.add('tooltipped'); 23 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 24 | }); 25 | 26 | clip.on('error', function(e) { 27 | inPre = e.trigger.parentNode.tagName == 'PRE'; 28 | e.trigger.setAttribute('aria-label', fallbackMessage(e.action)); 29 | e.trigger.classList.add('tooltipped'); 30 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 31 | document.addEventListener('copy', function(){ 32 | e.trigger.setAttribute('aria-label', 'Copied to clipboard!'); 33 | e.trigger.classList.add('tooltipped'); 34 | e.trigger.classList.add('tooltipped-' + (inPre ? 'w' : 's')); 35 | }); 36 | }); 37 | 38 | clipInit = true; 39 | } 40 | 41 | var copyNode = document.createElement('div'); 42 | copyNode.classList.add('copy-to-clipboard'); 43 | copyNode.setAttribute('title', 'Copy to clipboard'); 44 | 45 | code.after(copyNode); 46 | code.nextSibling.addEventListener('mouseleave', function() { 47 | this.setAttribute('aria-label', null); 48 | this.classList.remove('tooltipped'); 49 | this.classList.remove('tooltipped-s'); 50 | this.classList.remove('tooltipped-w'); 51 | }); 52 | } 53 | }); 54 | 55 | const tabs = document.querySelectorAll('[data-toggle="tab"]') || []; 56 | tabs.forEach(function(tab) { 57 | tab.addEventListener('click', function(e) { 58 | e.preventDefault(); 59 | e.stopPropagation(); 60 | 61 | const tabPane = document.querySelector(e.currentTarget.dataset.target); 62 | 63 | const activeTab = e.currentTarget.closest('.tabs ul').querySelector('li.is-active'); 64 | const activeTabPane = document.querySelector(activeTab.dataset.target); 65 | if (activeTab && !activeTab.isSameNode(e.currentTarget)) { 66 | activeTab.classList.remove('is-active'); 67 | if (activeTabPane) { 68 | activeTabPane.classList.remove('is-active'); 69 | } 70 | 71 | } 72 | 73 | e.currentTarget.classList.add('is-active'); 74 | if (tabPane) { 75 | tabPane.classList.add('is-active'); 76 | } 77 | }); 78 | }); 79 | }, false); -------------------------------------------------------------------------------- /docs/get-started/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Get-starteds on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 6 | Recent content in Get-starteds on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | Sat, 21 Mar 2020 00:00:00 +0000 10 | 11 | 12 | 13 | 14 | 15 | Installation 16 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 17 | Sat, 21 Mar 2020 00:00:00 +0000 18 | 19 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 20 | This component extends Bulma CSS Framework, so you need to have Bulma installed to use it. Installation First, let&rsquo;s install the component! There are several ways to get started with BulmaTagsInput. 1. NPM 2. CDN 3. Github Use npm to install the bulma-tagsinput package recommended 21 | npm install @creativebulma/bulma-tagsinput Use the jsDelivr CDN to link to the BulmaTagsInput stylesheet 22 | https://www.jsdelivr.com/package/npm/@creativebulma/bulma-tagsinput Use the GitHub repository to get the latest development version. 23 | 24 | 25 | 26 | Usage 27 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/usage/ 28 | Sat, 21 Mar 2020 00:00:00 +0000 29 | 30 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/usage/ 31 | Basic usage To easiest way to start with BulmaTagsInput is to add data-type=&quot;tags&quot; attribute or set type=&quot;tags&quot; to an input element and call BulmaTagsInput.attach(); to convert them all into a Tags input control. 32 | By default Tags input prevent duplicate entries and create selectable and removable tags. These options can be overiden either by JavaScript or by adding options into the input dataset (see Javascript API documentation). Preview Code Tags &lt;div class=&#34;field&#34;&gt; &lt;label class=&#34;label&#34;&gt;Tags&lt;/label&gt; &lt;div class=&#34;control&#34;&gt; &lt;input class=&#34;input&#34; type=&#34;text&#34; data-type=&#34;tags&#34; placeholder=&#34;Choose Tags&#34; value=&#34;One,Two&#34;&gt; &lt;/div&gt; &lt;/div&gt; 33 | 34 | 35 | 36 | Javascript API 37 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/javascript-api/ 38 | Sat, 21 Mar 2020 00:00:00 +0000 39 | 40 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/javascript-api/ 41 | JavaScript API Javascript API documentation BulmaTagsInput is available as a JavaScript object, so you can use it directly. 42 | // Instantiate on one element new BulmaTagsInput(selector, options); // Instantiate on multiple elements BulmaTagsInput.attach(selector, options); Arguments 43 | selector: query String returning a single Node or directly a Node options: see Options section Main differences between methods are when using attach: 44 | selector can be a query String returning a single Node or a NodeList, directly a Node or a NodeList DOM modifications will be observed to detect any new element responding to the given selector to automatically instantiate BulmaTagsInput on them with the given option. 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/docs/content/get-started/javascript-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Javascript API" 3 | date: "2020-03-21" 4 | menu: 5 | main: 6 | parent: 'get-started' 7 | weight: 3 8 | draft: false 9 | --- 10 | 11 | # JavaScript API 12 | ## Javascript API documentation 13 | BulmaTagsInput is available as a JavaScript object, so you can use it directly. 14 | 15 | ```javascript 16 | // Instantiate on one element 17 | new BulmaTagsInput(selector, options); 18 | 19 | // Instantiate on multiple elements 20 | BulmaTagsInput.attach(selector, options); 21 | ``` 22 | 23 | __Arguments__ 24 | * selector: query `String` returning a single `Node` or directly a `Node` 25 | * options: see [Options]({{< ref "/get-started/javascript-api#options" >}}) section 26 | 27 | {{< notification info >}} 28 | Main differences between methods are when using `attach`: 29 | * selector can be a query `String` returning a single `Node` or a `NodeList`, directly a `Node` or a `NodeList` 30 | * DOM modifications will be observed to detect any new element responding to the given selector to automatically instantiate BulmaTagsInput on them with the given option. 31 | {{< /notification >}} 32 | 33 | ### Access to BulmaTagsInput instance 34 | Whatever the way you use to instantiate BulmaTagsInput, all element on which BulmaTagsInput is applied will now contains a new `BulmaTagsInput` function which will let you access to the instance at any time. 35 | ```javascript 36 | var inputTags = document.getElementById('input-tags'); 37 | new BulmaTagsInput(inputTags); 38 | 39 | // Access to the BulmaTagsInput instance 40 | var btiInstance = inputTags.BulmaTagsInput(); 41 | 42 | // Call BulmaTagsInput method 43 | btiInstance.add('new Tag'); 44 | ``` 45 | ___ 46 | 47 | ## Options {#options} 48 | ### Customize plugin behavior with options 49 | You can easily manage the component behavior by passing an object of options to the constructor. 50 | 51 | Options can be set either through JavaScript or directly on the DOM as dataset of the element. 52 | {{< tabs tabTotal="2" tabID="1" tabName1="1. JavaScript" tabName2="2. Dataset" >}} 53 | {{< tab tabNum="1" >}} 54 | Provide options when instanciating plugin. Options will be applied to all element provided (or found by the given selector). 55 | ```javascript 56 | BulmaTagsInput.attach('input[data-type="tags"], input[type="tags"], select[data-type="tags"], select[type="tags"]', { 57 | allowDuplicates: false, 58 | caseSensitive: true, 59 | clearSelectionOnTyping: false, 60 | closeDropdownOnItemSelect: true, 61 | delimiter: ',', 62 | freeInput: true, 63 | highlightDuplicate: true, 64 | highlightMatchesString: true, 65 | itemValue: undefined, 66 | itemText: undefined, 67 | maxTags: undefined, 68 | maxChars: undefined, 69 | minChars: 1, 70 | noResultsLabel: 'No results found', 71 | placeholder: '', 72 | removable: true, 73 | searchMinChars: 1, 74 | searchOn: 'text', 75 | selectable: true, 76 | source: undefined, 77 | tagClass: 'is-rounded', 78 | trim: true 79 | }); 80 | ``` 81 | {{< /tab >}} 82 | 83 | {{< tab tabNum="2" >}} 84 | Add option directly to the element by using dataset attributes. This way, options can be specific to each element. These declaration will override any default option or option passed by the JavaScript instantiation. 85 | All you have to do is to use the [kebab-case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) notation of option and declare it as a `data attribute` of the HTML Element. 86 | ```html 87 | 88 | ``` 89 | {{< /tab >}} 90 | {{< /tabs >}} 91 | 92 | ### Options list 93 | All available option are described in the folowing table: 94 | {{< options >}} 95 | 96 | ___ 97 | 98 | # API {#api} 99 | ## Interact with the component 100 | {{< api >}} 101 | 102 | # Events {#events} 103 | This component provides some events you can listen to to react on state changes. 104 | {{< table source="events" >}} -------------------------------------------------------------------------------- /src/js/utils/events.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class EventEmitter 3 | * 4 | * @property {Array} _listeners 5 | */ 6 | export default class EventEmitter { 7 | /** 8 | * Construct EventEmitter 9 | * 10 | * @param {Array} listeners 11 | */ 12 | constructor(listeners = []) { 13 | this._listeners = new Map(listeners); 14 | this._events = new Map(); 15 | } 16 | 17 | /** 18 | * Destroys EventEmitter 19 | */ 20 | destroy() { 21 | this._listeners = {}; 22 | this.events = []; 23 | } 24 | 25 | /** 26 | * Count listeners registered for the provided eventName 27 | * 28 | * @param {string} eventName 29 | */ 30 | listenerCount(eventName) { 31 | if (!this._listeners.has(eventName)) { 32 | return 0; 33 | } 34 | 35 | return this._listeners.get(eventName).length; 36 | } 37 | 38 | /** 39 | * Subscribes on event eventName specified function 40 | * 41 | * @param {string} eventName 42 | * @param {function} listener 43 | */ 44 | on(eventName, listener) { 45 | this._addListener(eventName, listener, false); 46 | } 47 | 48 | /** 49 | * Subscribes on event name specified function to fire only once 50 | * 51 | * @param {string} eventName 52 | * @param {function} listener 53 | */ 54 | once(eventName, listener) { 55 | this._addListener(eventName, listener, true); 56 | } 57 | 58 | /** 59 | * Removes event with specified eventName. 60 | * 61 | * @param {string} eventName 62 | */ 63 | off(eventName) { 64 | this._removeListeners(eventName); 65 | } 66 | 67 | /** 68 | * Emits event with specified name and params. 69 | * 70 | * @param {string} eventName 71 | * @param eventArgs 72 | */ 73 | emit(eventName, ...eventArgs) { 74 | return this._applyEvents(eventName, eventArgs); 75 | } 76 | 77 | /** 78 | * Register a new listener 79 | * 80 | * @param {string} eventName 81 | * @param {function} listener 82 | * @param {bool} once 83 | */ 84 | _addListener(eventName, listener, once = false) { 85 | if (Array.isArray(eventName)) { 86 | eventName.forEach(e => this._addListener(e, listener, once)); 87 | } else { 88 | eventName = eventName.toString(); 89 | const split = eventName.split(/,|, | /); 90 | 91 | if (split.length > 1) { 92 | split.forEach(e => this._addListener(e, listener, once)); 93 | } else { 94 | if (!Array.isArray(this._listeners.get(eventName))) { 95 | this._listeners.set(eventName, []); 96 | } 97 | 98 | (this._listeners.get(eventName)).push({ 99 | once: once, 100 | fn: listener 101 | }); 102 | } 103 | } 104 | } 105 | 106 | /** 107 | * 108 | * @param {string|null} eventName 109 | */ 110 | _removeListeners(eventName = null) { 111 | if (eventName !== null) { 112 | if (Array.isArray(eventName)) { 113 | name.forEach(e => this.removeListeners(e)); 114 | } else { 115 | eventName = eventName.toString(); 116 | const split = eventName.split(/,|, | /); 117 | 118 | if (split.length > 1) { 119 | split.forEach(e => this.removeListeners(e)); 120 | } else { 121 | this._listeners.delete(eventName); 122 | } 123 | } 124 | } else { 125 | this._listeners = new Map(); 126 | } 127 | } 128 | 129 | /** 130 | * Applies arguments to specified event 131 | * 132 | * @param {string} eventName 133 | * @param {*[]} eventArguments 134 | * @protected 135 | */ 136 | _applyEvents(eventName, eventArguments) { 137 | let result = eventArguments; 138 | 139 | if (this._listeners.has(eventName)) { 140 | const listeners = this._listeners.get(eventName); 141 | let removableListeners = []; 142 | 143 | listeners.forEach((listener, index) => { 144 | if (result = listener.fn.apply(null, eventArguments)) { 145 | if (listener.once) { 146 | removableListeners.unshift(index); 147 | } 148 | } 149 | }); 150 | 151 | removableListeners.forEach(index => { 152 | listeners.splice(index, 1); 153 | }); 154 | 155 | return result; 156 | } 157 | 158 | return result[0]; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/sass/index.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | $tagsinput-selected-background-color: $primary !default 4 | $tagsinput-duplicate-animation: blinker .75s linear infinite !default 5 | 6 | .tags-input 7 | @extend %input 8 | align-content: flex-start 9 | display: flex 10 | flex-wrap: wrap 11 | height: auto 12 | min-height: 2.5em 13 | padding: 0 14 | position: relative 15 | 16 | .tag 17 | font-size: $size-normal 18 | margin: .1rem 19 | &:hover 20 | cursor: pointer 21 | &.is-selected 22 | background-color: $tagsinput-selected-background-color 23 | color: findColorInvert($tagsinput-selected-background-color) 24 | 25 | &.is-duplicate 26 | animation: $tagsinput-duplicate-animation 27 | 28 | .input 29 | border-color: transparent 30 | box-shadow: none 31 | display: inline-block 32 | flex: 1 0 auto 33 | height: 2.3rem 34 | margin: .1rem 35 | width: auto 36 | 37 | &.is-filter 38 | input 39 | color: $input-placeholder-color 40 | 41 | +placeholder 42 | color: $input-placeholder-color 43 | &.no-input 44 | input 45 | color: transparent 46 | text-shadow: 0 0 0 $input-placeholder-color 47 | 48 | +placeholder 49 | color: $input-placeholder-color 50 | text-shadow: none 51 | 52 | .dropdown-menu 53 | width: 100% 54 | 55 | .dropdown-content 56 | max-height: 250px 57 | overflow: hidden 58 | overflow-y: auto 59 | 60 | &.is-loading 61 | &::after 62 | @extend %loader 63 | left: 50% 64 | position: absolute !important 65 | top: 50% 66 | transform: translate(-50%, -50%) 67 | z-index: 4 68 | &::before 69 | background-color: rgba($background, .5) 70 | content: "" 71 | height: 100% 72 | left: 0 73 | position: absolute 74 | top: 0 75 | width: 100% 76 | z-index: 3 77 | 78 | .dropdown-item 79 | &:not(.empty-title) 80 | &:hover 81 | cursor: pointer 82 | 83 | &.empty-title 84 | color: $input-disabled-color 85 | text-align: center 86 | 87 | &:hover 88 | background: inherit 89 | color: $input-disabled-color 90 | 91 | mark 92 | &.is-highlighted 93 | background-color: $warning 94 | 95 | &.is-small 96 | .tag 97 | font-size: $size-small 98 | .input 99 | +control-small 100 | &.is-medium 101 | .tag 102 | font-size: $size-medium 103 | .input 104 | +control-medium 105 | &.is-large 106 | .tag 107 | font-size: $size-large 108 | .input 109 | +control-large 110 | 111 | &.is-disabled, 112 | &[disabled] 113 | background-color: $input-disabled-background-color 114 | border-color: $input-disabled-border-color 115 | box-shadow: none 116 | color: $input-disabled-color 117 | cursor: not-allowed 118 | 119 | .tag 120 | background-color: ligthen($input-disabled-background-color, 5%) 121 | color: $input-disabled-color 122 | cursor: not-allowed 123 | .delete 124 | background-color: darken($input-disabled-background-color, 5%) 125 | border-color: darken($input-disabled-border-color, 5%) 126 | box-shadow: none 127 | color: $input-disabled-color 128 | cursor: not-allowed 129 | 130 | .input 131 | background-color: $input-disabled-background-color 132 | border-color: $input-disabled-border-color 133 | box-shadow: none 134 | color: $input-disabled-color 135 | 136 | +placeholder 137 | color: $input-disabled-placeholder-color 138 | 139 | &[readonly] 140 | .input 141 | box-shadow: none 142 | 143 | &.is-active 144 | .dropdown-menu 145 | display: block 146 | 147 | @keyframes blinker 148 | 0% 149 | opacity: 1.0 150 | 50% 151 | opacity: 0.0 152 | 100% 153 | opacity: 1.0 -------------------------------------------------------------------------------- /src/docs/data/events.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": [ 3 | { 4 | "name": "Event name" 5 | }, 6 | { 7 | "name": "Description" 8 | }, 9 | { 10 | "name": "Example" 11 | } 12 | ], 13 | "body": [ 14 | { 15 | "name": "before.add", 16 | "description": "Trigerred before adding new tag. The concerned item is passed as parameter. You can modify the item before its treatment by returning the new item data or prevent tag to be added by returning false.", 17 | "example": "var inputTags = document.getElementById('myInputTag');\r\n\/\/ Example to capitalize a string item\r\ninputTags.BulmaTagsInput().on('before.add', function(item) {\r\n return item.charAt(0).toUpperCase() + item.slice(1);\r\n});\r\n\r\n\/\/ Example to accept string with only letters\r\ninputTags.BulmaTagsInput().on('before.add', function(item) {\r\n return item.value.match(\/^[A-Za-z]+$\/);\r\n});" 18 | }, 19 | { 20 | "name": "after.add", 21 | "description": "Triggered once a tag has been added. The added item and the related tag are passed in an object as parameter.", 22 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('after.add', function(data) {\r\n console.log(data.item);\r\n console.log(data.tag);\r\n});" 23 | }, 24 | { 25 | "name": "before.remove", 26 | "description": "Triggered before removing a tag. The concerned item is passed as parameter. You can prevent deletion by returning `false`.", 27 | "example": "var inputTags = document.getElementById('myInputTag');\r\n\/\/ Prevent all tags from being deleted\r\ninputTags.BulmaTagsInput().on('before.remove', function(item) {\r\n return false;\r\n});" 28 | }, 29 | { 30 | "name": "after.remove", 31 | "description": "Triggered once a tag has been removed. The removed item is passed as parameter.", 32 | "example": "var inputTags = document.getElementById('myInputTag');\r\n\/\/ Log all string items removes in the console\r\ninputTags.BulmaTagsInput().on('after.remove', function(item) {\r\n console.log(item + \" has been removed\";\r\n});" 33 | }, 34 | { 35 | "name": "before.flush", 36 | "description": "Triggered before flushing items. Items array is passed as parameter.", 37 | "example": "var inputTags = document.getElementById('myInputTag');\r\n\/\/ Log all string items concerned by the flush\r\ninputTags.BulmaTagsInput().on('before.flush', function(items) {\r\n items.forEach(function(item) {\r\n console.log(item + \" will be flush\";\r\n });\r\n});" 38 | }, 39 | { 40 | "name": "after.flush", 41 | "description": "Triggered after flushing items.", 42 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('after.flush', function(items) {\r\n \/\/ items should be an empty array\r\n});" 43 | }, 44 | { 45 | "name": "before.select", 46 | "description": "Triggered before selecting an item. The concerned item and related tag are passed in an Object as parameter.", 47 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('before.select', function(data) {\r\n console.log(data.item);\r\n console.log(data.tag);\r\n});" 48 | }, 49 | { 50 | "name": "after.select", 51 | "description": "Triggered once an item has been selected. The concerned item and related tag are passed in an Object as parameter.", 52 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('after.select', function(data) {\r\n console.log(data.item);\r\n console.log(data.tag);\r\n});" 53 | }, 54 | { 55 | "name": "before.unselect", 56 | "description": "Triggered before unselect an item. The concerned item and related tag are passed in an Object as parameter.", 57 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('before.unselect', function(data) {\r\n console.log(data.item);\r\n console.log(data.tag);\r\n});" 58 | }, 59 | { 60 | "name": "after.unselect", 61 | "description": "Triggered once an item has been unselected. The concerned item and related tag are passed in an Object as parameter.", 62 | "example": "var inputTags = document.getElementById('myInputTag');\r\ninputTags.BulmaTagsInput().on('after.select', function(data) {\r\n console.log(data.item);\r\n console.log(data.tag);\r\n});" 63 | } 64 | ] 65 | } -------------------------------------------------------------------------------- /src/docs/data/options.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "allowDuplicates", 4 | "description": "When true, the same tag can be added multiple times.", 5 | "type": "Boolean", 6 | "value": "false" 7 | }, 8 | { 9 | "name": "caseSensitive", 10 | "description": "When true, duplicate tags value check is case sensitive.", 11 | "type": "Boolean", 12 | "value": "true" 13 | }, 14 | { 15 | "name": "clearSelectionOnTyping", 16 | "description": "When true, tags will be unselected when new tag is entered.", 17 | "type": "Boolean", 18 | "value": "false" 19 | }, 20 | { 21 | "name": "closeDropdownOnItemSelect", 22 | "description": "When true, datalist will close automatically after an item have been selected.", 23 | "type": "Boolean", 24 | "value": "true" 25 | }, 26 | { 27 | "name": "delimiter", 28 | "description": "Multiple tags can be added at once. Delimiter is used to separate all tags. ", 29 | "type": "String", 30 | "value": "," 31 | }, 32 | { 33 | "name": "freeInput", 34 | "description": "When true, tags can be entered manually. This option is useful with select Tags inputs. Set to false automatically when using on select element.", 35 | "type": "Boolean", 36 | "value": "true" 37 | }, 38 | { 39 | "name": "highlightDuplicate", 40 | "description": "When true, if `allowDuplicates` option if false then the already existing tag will be temporarly and visually identified as duplicate ", 41 | "type": "Boolean", 42 | "value": "true" 43 | }, 44 | { 45 | "name": "highlightMatchesString", 46 | "description": "When true, identified matches strings when searching is highlighted.", 47 | "type": "Boolean", 48 | "value": "true" 49 | }, 50 | { 51 | "name": "itemText", 52 | "description": "When adding objects as tags, you can set itemText to the name of the property of item to use for a its tag's text. When this options is not set, the value of _itemValue_ will be used.", 53 | "type": "String", 54 | "value": "undefined" 55 | }, 56 | { 57 | "name": "itemValue", 58 | "description": "When adding objects as tags, itemValue must be set to the name of the property containing the item's value.", 59 | "type": "String", 60 | "value": "undefined" 61 | }, 62 | { 63 | "name": "maxTags", 64 | "description": "When set, no more than the given number of tags are allowed to add.", 65 | "type": "Integer", 66 | "value": "undefined" 67 | }, 68 | { 69 | "name": "maxChars", 70 | "description": "Defines the maximum length of a single tag.", 71 | "type": "Integer", 72 | "value": "undefined" 73 | }, 74 | { 75 | "name": "minChars", 76 | "description": "Defines the minimum length of a single tag.", 77 | "type": "Integer", 78 | "value": "1" 79 | }, 80 | { 81 | "name": "noResultsLabel", 82 | "description": "Empty dropdown label.", 83 | "type": "String", 84 | "value": "No results found" 85 | }, 86 | { 87 | "name": "placeholder", 88 | "description": "TagsInput placeholder text if original input doesn't have one.", 89 | "type": "String", 90 | "value": "undefined" 91 | }, 92 | { 93 | "name": "removable", 94 | "description": "When true, tags are removable either using the associted delete button or _backspace_ and _delete_ keys.", 95 | "type": "Boolean", 96 | "value": "true" 97 | }, 98 | { 99 | "name": "searchMinChars", 100 | "description": "Defines the minimum length of input value before loading auto-complete.", 101 | "type": "Integer", 102 | "value": "1" 103 | }, 104 | { 105 | "name": "searchOn", 106 | "description": "Defines on what dropdown item data do we search the entered value. Possible value: 'value' or 'text'.", 107 | "type": "String", 108 | "value": "text" 109 | }, 110 | { 111 | "name": "selectable", 112 | "description": "When true, tags can be selected either by mouse click or using _left_ or _right_ arrow keys.", 113 | "type": "Boolean", 114 | "value": "true" 115 | }, 116 | { 117 | "name": "source", 118 | "description": "Source of data proposed in dropdown (used for auto-complete).", 119 | "type": "Can be one of the following types:\n* `Array` of `Strings` / `Objects`\n* `Function` => `Array` of `Strings` / `Objects`\n* `Promise` => `Array` of `Strings` / `Objects`.", 120 | "value": "undefined" 121 | }, 122 | { 123 | "name": "tagClass", 124 | "description": "Classname applied to each tag.", 125 | "type": "String", 126 | "value": "is-rounded" 127 | }, 128 | { 129 | "name": "trim", 130 | "description": "When true, automatically removes all whitespace around tags.", 131 | "type": "Boolean", 132 | "value": "true" 133 | } 134 | ] 135 | -------------------------------------------------------------------------------- /docs/release/1.0.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | (2020-05-07) - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 106 |
107 | 128 | 129 |
130 |
131 |

Important fix for Form data

132 |
    133 |
  • 134 | 135 | 136 | 137 | 138 | fixed 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | Duplicate form data when submitting
  • 158 |
159 | 160 |
161 |
162 |
163 |
164 |
165 | 166 | 167 | 168 | 169 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /dist/css/bulma-tagsinput.min.css: -------------------------------------------------------------------------------- 1 | /*! @creativebulma/bulma-tagsinput v1.0.3 | (c) 2020 Gaetan | MIT License | https://github.com/CreativeBulma/bulma-tagsinput */ 2 | @keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}.tags-input .dropdown-menu .dropdown-content.is-loading:after{animation:a .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;width:1em}.tags-input{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;box-shadow:none;font-size:1rem;justify-content:flex-start;line-height:1.5;vertical-align:top}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{outline:0}.tags-input[disabled],fieldset[disabled] .tags-input{cursor:not-allowed}.tags-input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.tags-input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.is-hovered.tags-input,.tags-input:hover{border-color:#b5b5b5}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{border-color:#3273dc;box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.tags-input[disabled],fieldset[disabled] .tags-input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input[disabled]::-moz-placeholder,fieldset[disabled] .tags-input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]::-webkit-input-placeholder,fieldset[disabled] .tags-input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-moz-placeholder,fieldset[disabled] .tags-input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-ms-input-placeholder,fieldset[disabled] .tags-input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:0;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:3}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 .5em 1em -.125em hsla(0,0%,4%,.1),0 0 0 1px hsla(0,0%,4%,.02);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:left;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#3273dc;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:.5rem 0}.tags-input{align-content:flex-start;display:flex;flex-wrap:wrap;height:auto;min-height:2.5em;padding:0;position:relative}.tags-input .tag{font-size:1rem;margin:.1rem}.tags-input .tag:hover{cursor:pointer}.tags-input .tag.is-selected{background-color:#00d1b2;color:#fff}.tags-input .tag.is-duplicate{animation:b .75s linear infinite}.tags-input .input{border-color:transparent;box-shadow:none;display:inline-block;flex:1 0 auto;height:2.3rem;margin:.1rem;width:auto}.tags-input.is-filter input{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.no-input input{color:transparent;text-shadow:0 0 0 rgba(54,54,54,.3)}.tags-input.no-input input::-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input::-webkit-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-ms-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input .dropdown-menu{width:100%}.tags-input .dropdown-menu .dropdown-content{max-height:250px;overflow:hidden;overflow-y:auto}.tags-input .dropdown-menu .dropdown-content.is-loading:after{left:50%;position:absolute!important;top:50%;transform:translate(-50%,-50%);z-index:2}.tags-input .dropdown-menu .dropdown-content.is-loading:before{background-color:hsla(0,0%,96%,.5);content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:1}.tags-input .dropdown-menu .dropdown-item:not(.empty-title):hover{cursor:pointer}.tags-input .dropdown-menu .dropdown-item.empty-title{color:#7a7a7a;text-align:center}.tags-input .dropdown-menu .dropdown-item.empty-title:hover{background:inherit;color:#7a7a7a}.tags-input .dropdown-menu .dropdown-item mark.is-highlighted{background-color:#ffdd57}.tags-input.is-small .tag{font-size:.75rem}.tags-input.is-small .input{border-radius:2px;font-size:.75rem}.tags-input.is-medium .input,.tags-input.is-medium .tag{font-size:1.25rem}.tags-input.is-large .input,.tags-input.is-large .tag{font-size:1.5rem}.tags-input.is-disabled,.tags-input[disabled]{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag,.tags-input[disabled] .tag{background-color:ligthen(#f5f5f5,5%);color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag .delete,.tags-input[disabled] .tag .delete{background-color:#e8e8e8;border-color:#e8e8e8;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .input,.tags-input[disabled] .input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input.is-disabled .input::-moz-placeholder,.tags-input[disabled] .input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input::-webkit-input-placeholder,.tags-input[disabled] .input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-moz-placeholder,.tags-input[disabled] .input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-ms-input-placeholder,.tags-input[disabled] .input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[readonly] .input{box-shadow:none}.tags-input.is-active .dropdown-menu{display:block}@keyframes b{0%{opacity:1}50%{opacity:0}to{opacity:1}} -------------------------------------------------------------------------------- /docs/css/bulma-tagsinput.min.css: -------------------------------------------------------------------------------- 1 | /*! @creativebulma/bulma-tagsinput v1.0.1 | (c) 2020 Gaetan | MIT License | https://github.com/CreativeBulma/bulma-tagsinput */ 2 | @keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}.tags-input .dropdown-menu .dropdown-content.is-loading:after{animation:a .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;width:1em}.tags-input{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;box-shadow:none;font-size:1rem;justify-content:flex-start;line-height:1.5;vertical-align:top}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{outline:0}.tags-input[disabled],fieldset[disabled] .tags-input{cursor:not-allowed}.tags-input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.tags-input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.is-hovered.tags-input,.tags-input:hover{border-color:#b5b5b5}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{border-color:#3273dc;box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.tags-input[disabled],fieldset[disabled] .tags-input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input[disabled]::-moz-placeholder,fieldset[disabled] .tags-input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]::-webkit-input-placeholder,fieldset[disabled] .tags-input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-moz-placeholder,fieldset[disabled] .tags-input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-ms-input-placeholder,fieldset[disabled] .tags-input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:0;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:3}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 .5em 1em -.125em hsla(0,0%,4%,.1),0 0 0 1px hsla(0,0%,4%,.02);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:left;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#3273dc;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:.5rem 0}.tags-input{align-content:flex-start;display:flex;flex-wrap:wrap;height:auto;min-height:2.5em;padding:0;position:relative}.tags-input .tag{font-size:1rem;margin:.1rem}.tags-input .tag:hover{cursor:pointer}.tags-input .tag.is-selected{background-color:#00d1b2;color:#fff}.tags-input .tag.is-duplicate{animation:b .75s linear infinite}.tags-input .input{border-color:transparent;box-shadow:none;display:inline-block;flex:1 0 auto;height:2.3rem;margin:.1rem;width:auto}.tags-input.is-filter input{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.no-input input{color:transparent;text-shadow:0 0 0 rgba(54,54,54,.3)}.tags-input.no-input input::-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input::-webkit-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-ms-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input .dropdown-menu{width:100%}.tags-input .dropdown-menu .dropdown-content{max-height:250px;overflow:hidden;overflow-y:auto}.tags-input .dropdown-menu .dropdown-content.is-loading:after{left:50%;position:absolute!important;top:50%;transform:translate(-50%,-50%);z-index:2}.tags-input .dropdown-menu .dropdown-content.is-loading:before{background-color:hsla(0,0%,96%,.5);content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:1}.tags-input .dropdown-menu .dropdown-item:not(.empty-title):hover{cursor:pointer}.tags-input .dropdown-menu .dropdown-item.empty-title{color:#7a7a7a;text-align:center}.tags-input .dropdown-menu .dropdown-item.empty-title:hover{background:inherit;color:#7a7a7a}.tags-input .dropdown-menu .dropdown-item mark.is-highlighted{background-color:#ffdd57}.tags-input.is-small .tag{font-size:.75rem}.tags-input.is-small .input{border-radius:2px;font-size:.75rem}.tags-input.is-medium .input,.tags-input.is-medium .tag{font-size:1.25rem}.tags-input.is-large .input,.tags-input.is-large .tag{font-size:1.5rem}.tags-input.is-disabled,.tags-input[disabled]{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag,.tags-input[disabled] .tag{background-color:ligthen(#f5f5f5,5%);color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag .delete,.tags-input[disabled] .tag .delete{background-color:#e8e8e8;border-color:#e8e8e8;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .input,.tags-input[disabled] .input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input.is-disabled .input::-moz-placeholder,.tags-input[disabled] .input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input::-webkit-input-placeholder,.tags-input[disabled] .input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-moz-placeholder,.tags-input[disabled] .input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-ms-input-placeholder,.tags-input[disabled] .input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[readonly] .input{box-shadow:none}.tags-input.is-active .dropdown-menu{display:block}@keyframes b{0%{opacity:1}50%{opacity:0}to{opacity:1}} -------------------------------------------------------------------------------- /src/docs/static/css/bulma-tagsinput.min.css: -------------------------------------------------------------------------------- 1 | /*! @creativebulma/bulma-tagsinput v1.0.3 | (c) 2020 Gaetan | MIT License | https://github.com/CreativeBulma/bulma-tagsinput */ 2 | @keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}.tags-input .dropdown-menu .dropdown-content.is-loading:after{animation:a .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;width:1em}.tags-input{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;box-shadow:none;font-size:1rem;justify-content:flex-start;line-height:1.5;vertical-align:top}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{outline:0}.tags-input[disabled],fieldset[disabled] .tags-input{cursor:not-allowed}.tags-input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.tags-input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.is-hovered.tags-input,.tags-input:hover{border-color:#b5b5b5}.is-active.tags-input,.is-focused.tags-input,.tags-input:active,.tags-input:focus{border-color:#3273dc;box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.tags-input[disabled],fieldset[disabled] .tags-input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input[disabled]::-moz-placeholder,fieldset[disabled] .tags-input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]::-webkit-input-placeholder,fieldset[disabled] .tags-input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-moz-placeholder,fieldset[disabled] .tags-input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[disabled]:-ms-input-placeholder,fieldset[disabled] .tags-input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:0;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:3}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 .5em 1em -.125em hsla(0,0%,4%,.1),0 0 0 1px hsla(0,0%,4%,.02);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:left;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#3273dc;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:.5rem 0}.tags-input{align-content:flex-start;display:flex;flex-wrap:wrap;height:auto;min-height:2.5em;padding:0;position:relative}.tags-input .tag{font-size:1rem;margin:.1rem}.tags-input .tag:hover{cursor:pointer}.tags-input .tag.is-selected{background-color:#00d1b2;color:#fff}.tags-input .tag.is-duplicate{animation:b .75s linear infinite}.tags-input .input{border-color:transparent;box-shadow:none;display:inline-block;flex:1 0 auto;height:2.3rem;margin:.1rem;width:auto}.tags-input.is-filter input{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-moz-placeholder{color:rgba(54,54,54,.3)}.tags-input.is-filter input:-ms-input-placeholder{color:rgba(54,54,54,.3)}.tags-input.no-input input{color:transparent;text-shadow:0 0 0 rgba(54,54,54,.3)}.tags-input.no-input input::-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input::-webkit-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-moz-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input.no-input input:-ms-input-placeholder{color:rgba(54,54,54,.3);text-shadow:none}.tags-input .dropdown-menu{width:100%}.tags-input .dropdown-menu .dropdown-content{max-height:250px;overflow:hidden;overflow-y:auto}.tags-input .dropdown-menu .dropdown-content.is-loading:after{left:50%;position:absolute!important;top:50%;transform:translate(-50%,-50%);z-index:2}.tags-input .dropdown-menu .dropdown-content.is-loading:before{background-color:hsla(0,0%,96%,.5);content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:1}.tags-input .dropdown-menu .dropdown-item:not(.empty-title):hover{cursor:pointer}.tags-input .dropdown-menu .dropdown-item.empty-title{color:#7a7a7a;text-align:center}.tags-input .dropdown-menu .dropdown-item.empty-title:hover{background:inherit;color:#7a7a7a}.tags-input .dropdown-menu .dropdown-item mark.is-highlighted{background-color:#ffdd57}.tags-input.is-small .tag{font-size:.75rem}.tags-input.is-small .input{border-radius:2px;font-size:.75rem}.tags-input.is-medium .input,.tags-input.is-medium .tag{font-size:1.25rem}.tags-input.is-large .input,.tags-input.is-large .tag{font-size:1.5rem}.tags-input.is-disabled,.tags-input[disabled]{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag,.tags-input[disabled] .tag{background-color:ligthen(#f5f5f5,5%);color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .tag .delete,.tags-input[disabled] .tag .delete{background-color:#e8e8e8;border-color:#e8e8e8;box-shadow:none;color:#7a7a7a;cursor:not-allowed}.tags-input.is-disabled .input,.tags-input[disabled] .input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.tags-input.is-disabled .input::-moz-placeholder,.tags-input[disabled] .input::-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input::-webkit-input-placeholder,.tags-input[disabled] .input::-webkit-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-moz-placeholder,.tags-input[disabled] .input:-moz-placeholder{color:hsla(0,0%,48%,.3)}.tags-input.is-disabled .input:-ms-input-placeholder,.tags-input[disabled] .input:-ms-input-placeholder{color:hsla(0,0%,48%,.3)}.tags-input[readonly] .input{box-shadow:none}.tags-input.is-active .dropdown-menu{display:block}@keyframes b{0%{opacity:1}50%{opacity:0}to{opacity:1}} -------------------------------------------------------------------------------- /docs/release/1.0.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | (2020-05-15) - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 106 |
107 | 128 | 129 |
130 |
131 |

Important fixes for select based TagsInput

132 | 184 | 185 |
186 |
187 |
188 |
189 |
190 | 191 | 192 | 193 | 194 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /docs/release/1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | (2020-05-02) - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 106 |
107 | 128 | 129 |
130 |
131 |

First working version

132 |
    133 |
  • 134 | 135 | 136 | added 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Works with Input, Select, Multiple Select elements
  • 148 |
  • 149 | 150 | 151 | added 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | Customize behavior with lots of options
  • 163 |
  • 164 | 165 | 166 | added 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | Events API
  • 178 |
  • 179 | 180 | 181 | added 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | External data source management
  • 193 |
  • 194 | 195 | 196 | added 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | Filtering/Search
  • 208 |
209 | 210 |
211 |
212 |
213 |
214 |
215 | 216 | 217 | 218 | 219 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /docs/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Introduction on BulmaTagsInput 5 | https://demo.creativebulma.net/components/tagsinput/1.0/ 6 | Recent content in Introduction on BulmaTagsInput 7 | Hugo -- gohugo.io 8 | en-us 9 | Sat, 21 Mar 2020 00:00:00 +0000 10 | 11 | 12 | 13 | 14 | 15 | (2020-05-15) 16 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.2/ 17 | Fri, 15 May 2020 10:46:47 +0200 18 | 19 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.2/ 20 | Important fixes for select based TagsInput 21 | fixed Multiple pre-selected options not working fixed Tags still removable when select is disabled 22 | 23 | 24 | 25 | (2020-05-07) 26 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.1/ 27 | Thu, 07 May 2020 10:46:47 +0200 28 | 29 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1.0.1/ 30 | Important fix for Form data 31 | fixed Duplicate form data when submitting 32 | 33 | 34 | 35 | (2020-05-02) 36 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1/ 37 | Sat, 02 May 2020 10:46:47 +0200 38 | 39 | https://demo.creativebulma.net/components/tagsinput/1.0/release/1/ 40 | First working version 41 | added Works with Input, Select, Multiple Select elements added Customize behavior with lots of options added Events API added External data source management added Filtering/Search 42 | 43 | 44 | 45 | Customize 46 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/customize/ 47 | Sat, 21 Mar 2020 00:00:00 +0000 48 | 49 | https://demo.creativebulma.net/components/tagsinput/1.0/how-to/customize/ 50 | How-To Customize This component has been designed to be easily customizable. 51 | There is 2 ways to customize it, depending on the way you integrate this component into your project. 52 | Sass If you use the Sass source into your project, all you have to do is to customize variables before importing the component. 53 | $tagsinput-selected-background-color: $dark @import &#39;@creativebulma/bulma-tagsinput&#39; Variables Variable name Description Default value $tagsinput-selected-background-color $primary $tagsinput-duplicate-animation blinker . 54 | 55 | 56 | 57 | Installation 58 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 59 | Sat, 21 Mar 2020 00:00:00 +0000 60 | 61 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/ 62 | This component extends Bulma CSS Framework, so you need to have Bulma installed to use it. Installation First, let&rsquo;s install the component! There are several ways to get started with BulmaTagsInput. 1. NPM 2. CDN 3. Github Use npm to install the bulma-tagsinput package recommended 63 | npm install @creativebulma/bulma-tagsinput Use the jsDelivr CDN to link to the BulmaTagsInput stylesheet 64 | https://www.jsdelivr.com/package/npm/@creativebulma/bulma-tagsinput Use the GitHub repository to get the latest development version. 65 | 66 | 67 | 68 | Usage 69 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/usage/ 70 | Sat, 21 Mar 2020 00:00:00 +0000 71 | 72 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/usage/ 73 | Basic usage To easiest way to start with BulmaTagsInput is to add data-type=&quot;tags&quot; attribute or set type=&quot;tags&quot; to an input element and call BulmaTagsInput.attach(); to convert them all into a Tags input control. 74 | By default Tags input prevent duplicate entries and create selectable and removable tags. These options can be overiden either by JavaScript or by adding options into the input dataset (see Javascript API documentation). Preview Code Tags &lt;div class=&#34;field&#34;&gt; &lt;label class=&#34;label&#34;&gt;Tags&lt;/label&gt; &lt;div class=&#34;control&#34;&gt; &lt;input class=&#34;input&#34; type=&#34;text&#34; data-type=&#34;tags&#34; placeholder=&#34;Choose Tags&#34; value=&#34;One,Two&#34;&gt; &lt;/div&gt; &lt;/div&gt; 75 | 76 | 77 | 78 | Changelog 79 | https://demo.creativebulma.net/components/tagsinput/1.0/changelog/ 80 | Sat, 02 May 2020 00:00:00 +0000 81 | 82 | https://demo.creativebulma.net/components/tagsinput/1.0/changelog/ 83 | Changelog v1.0.2 (2020-05-15) Important fixes for select based TagsInput 84 | fixed Multiple pre-selected options not working fixed Tags still removable when select is disabled v1.0.1 (2020-05-07) Important fix for Form data 85 | fixed Duplicate form data when submitting v1.0.0 (2020-05-02) First working version 86 | added Works with Input, Select, Multiple Select elements added Customize behavior with lots of options added Events API added External data source management added Filtering/Search 87 | 88 | 89 | 90 | Javascript API 91 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/javascript-api/ 92 | Sat, 21 Mar 2020 00:00:00 +0000 93 | 94 | https://demo.creativebulma.net/components/tagsinput/1.0/get-started/javascript-api/ 95 | JavaScript API Javascript API documentation BulmaTagsInput is available as a JavaScript object, so you can use it directly. 96 | // Instantiate on one element new BulmaTagsInput(selector, options); // Instantiate on multiple elements BulmaTagsInput.attach(selector, options); Arguments 97 | selector: query String returning a single Node or directly a Node options: see Options section Main differences between methods are when using attach: 98 | selector can be a query String returning a single Node or a NodeList, directly a Node or a NodeList DOM modifications will be observed to detect any new element responding to the given selector to automatically instantiate BulmaTagsInput on them with the given option. 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Introduction - BulmaTagsInput 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 | 34 |
35 |
36 | 107 |
108 | 129 | 130 |
131 |
132 |

Introduction

133 |

What is BulmaTagsInput

134 |

BulmaTagsInput is a 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Bulma extension which brings a full-featured user interface for managing tags supporting autocomplete to your project.

145 | 146 |
If you enjoy this component, have a look at our MarketPlace and discover Free and Premium Bulma components and Templates.
147 |

License

148 |

BulmaTagsInput is © 2020 by CreativeBulma.

149 |

BulmaTagsInput is distributed under MIT license.

150 |

Contributing

151 |

Contribution are welcome!

152 |

You found a bug, a typo issue ? Feel free to create a PR on the github repository of this project.

153 |

When contributing to this project, please first discuss the change you wish to make via issue on the github repository, email, or any other method with the owners of this project before making a change.

154 | 155 |
156 |
157 |
158 |
159 |
160 | 161 | 162 | 163 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/css/docs.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 15px; 3 | font-weight: 400; 4 | } 5 | 6 | html, 7 | body, 8 | .is-fullheight { 9 | height: 100%; 10 | min-height: 100%; 11 | overflow-y: auto; 12 | } 13 | 14 | body { 15 | background-color: #fff; 16 | color: #5a6270 !important; 17 | font-family: Source Sans Pro, sans-serif; 18 | } 19 | 20 | .is-fullheight .navbar+.is-fullheight { 21 | height: calc(100% - 3.25rem); 22 | min-height: calc(100% - 3.25rem); 23 | } 24 | 25 | .brand { 26 | line-height: 1.5; 27 | padding: .5rem .75rem; 28 | height: 3.25rem; 29 | display: block; 30 | font-weight: 700; 31 | } 32 | 33 | .navbar a:not(.button) { 34 | color: #5a6270 !important; 35 | text-decoration: none; 36 | } 37 | .navbar a:not(.button):hover { 38 | color: #6056FF !important; 39 | text-decoration: none; 40 | } 41 | 42 | .content h1, 43 | .content h2 { 44 | font-weight: 500; 45 | } 46 | 47 | .content h1+h2 { 48 | margin-top: 0 !important; 49 | font-size: 1.3em; 50 | font-weight: 500; 51 | color: #5A6270; 52 | padding-bottom: calc(1.45rem - 1px); 53 | border-bottom: 1px solid #dee2e7; 54 | } 55 | 56 | .content h2+h3 { 57 | margin-top: 0 !important; 58 | font-size: 1.125em; 59 | font-weight: 500; 60 | color: #5A6270; 61 | padding-bottom: calc(1.45rem - 1px); 62 | } 63 | 64 | .content h1, 65 | .content h2, 66 | .content h3 { 67 | color: #2f353f; 68 | } 69 | 70 | .content h4, 71 | .content h5, 72 | .content h6 { 73 | color: #5a6270; 74 | margin: 1em 0 .8em 0; 75 | } 76 | 77 | a:not(.button) { 78 | color: #6056FF; 79 | } 80 | 81 | a:not(.button):hover { 82 | text-decoration: underline; 83 | } 84 | 85 | .menu-list { 86 | padding: 3rem 0; 87 | } 88 | 89 | .menu-list li ul { 90 | font-size: .85rem; 91 | } 92 | 93 | .menu-item:not(.has-dropdown) { 94 | padding: .5rem 1rem; 95 | } 96 | 97 | .menu { 98 | background-color: transparent !important; 99 | box-shadow: none !important; 100 | border-right: 1px solid #DEE2E7; 101 | overflow-y: auto; 102 | } 103 | 104 | .menu a { 105 | color: #5a6270 !important; 106 | } 107 | 108 | .menu a:hover { 109 | text-decoration: none; 110 | } 111 | 112 | ol li { 113 | margin-bottom: 1.25em; 114 | } 115 | 116 | hr { 117 | margin: 4rem 0; 118 | } 119 | hr.is-small { 120 | margin: 2rem 0; 121 | margin-bottom: 1rem; 122 | } 123 | 124 | code, 125 | kbd, 126 | pre, 127 | samp { 128 | font-family: "Consolas", menlo, monospace; 129 | font-size: 92%; 130 | } 131 | 132 | code { 133 | padding: .1em .3em; 134 | border-radius: .3em; 135 | font-size: .9em; 136 | color: #6056FF; 137 | background: #ebeef0; 138 | overflow-x: auto; 139 | } 140 | 141 | code+.copy-to-clipboard { 142 | margin-left: -1px; 143 | border-left: 0 !important; 144 | font-size: inherit !important; 145 | vertical-align: middle; 146 | height: 24px; 147 | top: 0; 148 | } 149 | 150 | pre { 151 | padding: 1rem; 152 | background: #f5f6fa !important; 153 | border: 0; 154 | border-radius: 2px; 155 | line-height: 1.15; 156 | position: relative; 157 | border: 1px solid rgb(222, 226, 231); 158 | } 159 | 160 | pre code { 161 | color: #586e75; 162 | background: inherit; 163 | white-space: inherit; 164 | border: 0; 165 | padding: 0; 166 | margin: 0; 167 | font-size: 0.875em; 168 | line-height: 1.375; 169 | max-width: 100%; 170 | width: 100%; 171 | display: block; 172 | overflow: auto; 173 | } 174 | 175 | .copy-to-clipboard { 176 | background-image: url(../images/clippy.svg); 177 | background-position: 50% 50%; 178 | background-size: 16px 16px; 179 | background-repeat: no-repeat; 180 | width: 27px; 181 | height: 1.45rem; 182 | top: -1px; 183 | display: inline-block; 184 | vertical-align: middle; 185 | position: relative; 186 | color: #586e75; 187 | background-color: #FFF7DD; 188 | margin-left: -.2rem; 189 | cursor: pointer; 190 | border-radius: 0 2px 2px 0; 191 | margin-bottom: 1px; 192 | } 193 | 194 | .copy-to-clipboard:hover { 195 | background-color: #E8E2CD; 196 | } 197 | 198 | pre .copy-to-clipboard { 199 | position: absolute; 200 | right: 4px; 201 | top: 4px; 202 | background-color: white; 203 | color: #ccc; 204 | border-radius: 2px; 205 | } 206 | 207 | pre .copy-to-clipboard:hover { 208 | background-color: whitesmoke; 209 | color: #fff !important; 210 | } 211 | 212 | .notification { 213 | background: #f9f9f9 !important; 214 | border-left: 3px solid #6056FF; 215 | color: #67757c !important; 216 | } 217 | 218 | .notification.is-white { 219 | border-left-color: white; 220 | } 221 | 222 | .notification.is-black { 223 | border-left-color: #0a0a0a; 224 | } 225 | 226 | .notification.is-light { 227 | border-left-color: whitesmoke; 228 | } 229 | 230 | .notification.is-dark { 231 | border-left-color: #2f3d4a; 232 | } 233 | 234 | .notification.is-primary { 235 | border-left-color: #6056FF; 236 | } 237 | 238 | .notification.is-link { 239 | border-left-color: #3273dc; 240 | } 241 | 242 | .notification.is-info { 243 | border-left-color: #37aee3; 244 | } 245 | 246 | .notification.is-success { 247 | border-left-color: #26c6da; 248 | } 249 | 250 | .notification.is-warning { 251 | border-left-color: #ffb22b; 252 | } 253 | 254 | .notification.is-danger { 255 | border-left-color: #ef5350; 256 | } 257 | 258 | .tabs { 259 | margin-bottom: 0 !important; 260 | } 261 | 262 | .tabs ul { 263 | margin-left: 0; 264 | margin-top: 0; 265 | } 266 | 267 | .tabs ul li a { 268 | color: #5a6270 !important; 269 | border-bottom: 2px solid transparent; 270 | padding: 1em; 271 | } 272 | 273 | .tabs ul li.is-active a { 274 | color: #6056FF !important; 275 | border-bottom-color: #6056FF !important; 276 | } 277 | 278 | .tabs ul li a:hover { 279 | text-decoration: none; 280 | } 281 | 282 | .tab-content .tab-pane { 283 | display: none; 284 | padding: 1em; 285 | } 286 | 287 | .tab-content .tab-pane.is-active { 288 | display: block; 289 | } 290 | 291 | .preview { 292 | border: 1px solid rgb(222, 226, 231); 293 | border-radius: 3px; 294 | margin-bottom: 1.5rem; 295 | } 296 | 297 | .preview .tab-content .tab-pane:nth-child(2) { 298 | background-color: #f5f6fa; 299 | } 300 | 301 | .preview .tab-content .tab-pane:nth-child(2) pre { 302 | border: none !important; 303 | } 304 | 305 | .content table td { 306 | padding: 1.25em .75em; 307 | } 308 | 309 | .symbol { 310 | display: block; 311 | font-size: 1.5rem; 312 | padding: 1rem 0; 313 | text-decoration: none !important; 314 | } 315 | 316 | .symbol .symbol-name { 317 | font-size: 85.4%; 318 | font-weight: 700; 319 | color: #050607; 320 | padding: 2px 5px 3px; 321 | background-color: rgba(238, 240, 244, 0.74); 322 | border-radius: 3px; 323 | } 324 | 325 | .symbol .symbol-separator { 326 | background-color: transparent; 327 | color: #aaafbd; 328 | } 329 | 330 | .symbol .symbol-type { 331 | color: #7e879c; 332 | font-weight: 400; 333 | background-color: transparent; 334 | } 335 | 336 | 337 | .param { 338 | margin-bottom: .5rem !important; 339 | } 340 | 341 | .param+.param-description { 342 | margin-bottom: 1.5rem; 343 | } 344 | 345 | .param-name, 346 | .param-type { 347 | font-size: 85.4%; 348 | font-weight: 700; 349 | color: #050607; 350 | padding: 2px 5px 3px; 351 | background-color: rgba(238, 240, 244, 0.74); 352 | border-radius: 3px; 353 | } 354 | 355 | .param-type { 356 | font-size: 1em; 357 | font-weight: 400; 358 | color: #37aee3; 359 | } 360 | 361 | .param-type .param-type-separator { 362 | color: #7a7a7a; 363 | } 364 | 365 | .param-separator { 366 | background-color: transparent; 367 | color: #aaafbd; 368 | margin: .25rem; 369 | } 370 | 371 | .param-description { 372 | padding: 10px 20px 7px; 373 | border-top: 1px solid #eef0f5 !important; 374 | background: #fbfbfb; 375 | } -------------------------------------------------------------------------------- /src/docs/themes/creativebulma/static/css/docs.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 15px; 3 | font-weight: 400; 4 | } 5 | 6 | html, 7 | body, 8 | .is-fullheight { 9 | height: 100%; 10 | min-height: 100%; 11 | overflow-y: auto; 12 | } 13 | 14 | body { 15 | background-color: #fff; 16 | color: #5a6270 !important; 17 | font-family: Source Sans Pro, sans-serif; 18 | } 19 | 20 | .is-fullheight .navbar+.is-fullheight { 21 | height: calc(100% - 3.25rem); 22 | min-height: calc(100% - 3.25rem); 23 | } 24 | 25 | .brand { 26 | line-height: 1.5; 27 | padding: .5rem .75rem; 28 | height: 3.25rem; 29 | display: block; 30 | font-weight: 700; 31 | } 32 | 33 | .navbar a:not(.button) { 34 | color: #5a6270 !important; 35 | text-decoration: none; 36 | } 37 | .navbar a:not(.button):hover { 38 | color: #6056FF !important; 39 | text-decoration: none; 40 | } 41 | 42 | .content h1, 43 | .content h2 { 44 | font-weight: 500; 45 | } 46 | 47 | .content h1+h2 { 48 | margin-top: 0 !important; 49 | font-size: 1.3em; 50 | font-weight: 500; 51 | color: #5A6270; 52 | padding-bottom: calc(1.45rem - 1px); 53 | border-bottom: 1px solid #dee2e7; 54 | } 55 | 56 | .content h2+h3 { 57 | margin-top: 0 !important; 58 | font-size: 1.125em; 59 | font-weight: 500; 60 | color: #5A6270; 61 | padding-bottom: calc(1.45rem - 1px); 62 | } 63 | 64 | .content h1, 65 | .content h2, 66 | .content h3 { 67 | color: #2f353f; 68 | } 69 | 70 | .content h4, 71 | .content h5, 72 | .content h6 { 73 | color: #5a6270; 74 | margin: 1em 0 .8em 0; 75 | } 76 | 77 | a:not(.button) { 78 | color: #6056FF; 79 | } 80 | 81 | a:not(.button):hover { 82 | text-decoration: underline; 83 | } 84 | 85 | .menu-list { 86 | padding: 3rem 0; 87 | } 88 | 89 | .menu-list li ul { 90 | font-size: .85rem; 91 | } 92 | 93 | .menu-item:not(.has-dropdown) { 94 | padding: .5rem 1rem; 95 | } 96 | 97 | .menu { 98 | background-color: transparent !important; 99 | box-shadow: none !important; 100 | border-right: 1px solid #DEE2E7; 101 | overflow-y: auto; 102 | } 103 | 104 | .menu a { 105 | color: #5a6270 !important; 106 | } 107 | 108 | .menu a:hover { 109 | text-decoration: none; 110 | } 111 | 112 | ol li { 113 | margin-bottom: 1.25em; 114 | } 115 | 116 | hr { 117 | margin: 4rem 0; 118 | } 119 | hr.is-small { 120 | margin: 2rem 0; 121 | margin-bottom: 1rem; 122 | } 123 | 124 | code, 125 | kbd, 126 | pre, 127 | samp { 128 | font-family: "Consolas", menlo, monospace; 129 | font-size: 92%; 130 | } 131 | 132 | code { 133 | padding: .1em .3em; 134 | border-radius: .3em; 135 | font-size: .9em; 136 | color: #6056FF; 137 | background: #ebeef0; 138 | overflow-x: auto; 139 | } 140 | 141 | code+.copy-to-clipboard { 142 | margin-left: -1px; 143 | border-left: 0 !important; 144 | font-size: inherit !important; 145 | vertical-align: middle; 146 | height: 24px; 147 | top: 0; 148 | } 149 | 150 | pre { 151 | padding: 1rem; 152 | background: #f5f6fa !important; 153 | border: 0; 154 | border-radius: 2px; 155 | line-height: 1.15; 156 | position: relative; 157 | border: 1px solid rgb(222, 226, 231); 158 | } 159 | 160 | pre code { 161 | color: #586e75; 162 | background: inherit; 163 | white-space: inherit; 164 | border: 0; 165 | padding: 0; 166 | margin: 0; 167 | font-size: 0.875em; 168 | line-height: 1.375; 169 | max-width: 100%; 170 | width: 100%; 171 | display: block; 172 | overflow: auto; 173 | } 174 | 175 | .copy-to-clipboard { 176 | background-image: url(../images/clippy.svg); 177 | background-position: 50% 50%; 178 | background-size: 16px 16px; 179 | background-repeat: no-repeat; 180 | width: 27px; 181 | height: 1.45rem; 182 | top: -1px; 183 | display: inline-block; 184 | vertical-align: middle; 185 | position: relative; 186 | color: #586e75; 187 | background-color: #FFF7DD; 188 | margin-left: -.2rem; 189 | cursor: pointer; 190 | border-radius: 0 2px 2px 0; 191 | margin-bottom: 1px; 192 | } 193 | 194 | .copy-to-clipboard:hover { 195 | background-color: #E8E2CD; 196 | } 197 | 198 | pre .copy-to-clipboard { 199 | position: absolute; 200 | right: 4px; 201 | top: 4px; 202 | background-color: white; 203 | color: #ccc; 204 | border-radius: 2px; 205 | } 206 | 207 | pre .copy-to-clipboard:hover { 208 | background-color: whitesmoke; 209 | color: #fff !important; 210 | } 211 | 212 | .notification { 213 | background: #f9f9f9 !important; 214 | border-left: 3px solid #6056FF; 215 | color: #67757c !important; 216 | } 217 | 218 | .notification.is-white { 219 | border-left-color: white; 220 | } 221 | 222 | .notification.is-black { 223 | border-left-color: #0a0a0a; 224 | } 225 | 226 | .notification.is-light { 227 | border-left-color: whitesmoke; 228 | } 229 | 230 | .notification.is-dark { 231 | border-left-color: #2f3d4a; 232 | } 233 | 234 | .notification.is-primary { 235 | border-left-color: #6056FF; 236 | } 237 | 238 | .notification.is-link { 239 | border-left-color: #3273dc; 240 | } 241 | 242 | .notification.is-info { 243 | border-left-color: #37aee3; 244 | } 245 | 246 | .notification.is-success { 247 | border-left-color: #26c6da; 248 | } 249 | 250 | .notification.is-warning { 251 | border-left-color: #ffb22b; 252 | } 253 | 254 | .notification.is-danger { 255 | border-left-color: #ef5350; 256 | } 257 | 258 | .tabs { 259 | margin-bottom: 0 !important; 260 | } 261 | 262 | .tabs ul { 263 | margin-left: 0; 264 | margin-top: 0; 265 | } 266 | 267 | .tabs ul li a { 268 | color: #5a6270 !important; 269 | border-bottom: 2px solid transparent; 270 | padding: 1em; 271 | } 272 | 273 | .tabs ul li.is-active a { 274 | color: #6056FF !important; 275 | border-bottom-color: #6056FF !important; 276 | } 277 | 278 | .tabs ul li a:hover { 279 | text-decoration: none; 280 | } 281 | 282 | .tab-content .tab-pane { 283 | display: none; 284 | padding: 1em; 285 | } 286 | 287 | .tab-content .tab-pane.is-active { 288 | display: block; 289 | } 290 | 291 | .preview { 292 | border: 1px solid rgb(222, 226, 231); 293 | border-radius: 3px; 294 | margin-bottom: 1.5rem; 295 | } 296 | 297 | .preview .tab-content .tab-pane:nth-child(2) { 298 | background-color: #f5f6fa; 299 | } 300 | 301 | .preview .tab-content .tab-pane:nth-child(2) pre { 302 | border: none !important; 303 | } 304 | 305 | .content table td { 306 | padding: 1.25em .75em; 307 | } 308 | 309 | .symbol { 310 | display: block; 311 | font-size: 1.5rem; 312 | padding: 1rem 0; 313 | text-decoration: none !important; 314 | } 315 | 316 | .symbol .symbol-name { 317 | font-size: 85.4%; 318 | font-weight: 700; 319 | color: #050607; 320 | padding: 2px 5px 3px; 321 | background-color: rgba(238, 240, 244, 0.74); 322 | border-radius: 3px; 323 | } 324 | 325 | .symbol .symbol-separator { 326 | background-color: transparent; 327 | color: #aaafbd; 328 | } 329 | 330 | .symbol .symbol-type { 331 | color: #7e879c; 332 | font-weight: 400; 333 | background-color: transparent; 334 | } 335 | 336 | 337 | .param { 338 | margin-bottom: .5rem !important; 339 | } 340 | 341 | .param+.param-description { 342 | margin-bottom: 1.5rem; 343 | } 344 | 345 | .param-name, 346 | .param-type { 347 | font-size: 85.4%; 348 | font-weight: 700; 349 | color: #050607; 350 | padding: 2px 5px 3px; 351 | background-color: rgba(238, 240, 244, 0.74); 352 | border-radius: 3px; 353 | } 354 | 355 | .param-type { 356 | font-size: 1em; 357 | font-weight: 400; 358 | color: #37aee3; 359 | } 360 | 361 | .param-type .param-type-separator { 362 | color: #7a7a7a; 363 | } 364 | 365 | .param-separator { 366 | background-color: transparent; 367 | color: #aaafbd; 368 | margin: .25rem; 369 | } 370 | 371 | .param-description { 372 | padding: 10px 20px 7px; 373 | border-top: 1px solid #eef0f5 !important; 374 | background: #fbfbfb; 375 | } -------------------------------------------------------------------------------- /docs/how-to/customize/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Customize - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 106 |
107 | 128 | 129 |
130 |
131 |

How-To

132 |

Customize

133 |

This component has been designed to be easily customizable.

134 |

There is 2 ways to customize it, depending on the way you integrate this component into your project.

135 |

Sass

136 |

If you use the Sass source into your project, all you have to do is to customize variables before importing the component.

137 |
$tagsinput-selected-background-color: $dark
138 | 
139 | @import '@creativebulma/bulma-tagsinput'
140 | 

Variables

141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 |
Variable nameDescriptionDefault value
$tagsinput-selected-background-color$primary
$tagsinput-duplicate-animationblinker .75s linear infinite
165 |

CSS

166 |

If you uses the CSS version you have to customize Sass source files then rebuild the CSS file.

167 |

First, let’s install some packages!

168 |
npm install
169 | 

This command will install all development required package.

170 |

Customize

171 |

Customize Sass variables defined within src/sass/index.sass file.

172 |

Build

173 |

You can build CSS files by launching the build process with the command:

174 |
npm run build
175 | 

Styles are built using node-sass from src/sass directory and minify them. 176 | Built files will be copied into /dist directory (can be customized within package.json).

177 | 178 |
179 |
180 |
181 |
182 |
183 | 184 | 185 | 186 | 187 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/docs/content/get-started/usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Usage" 3 | date: "2020-03-21" 4 | menu: 5 | main: 6 | parent: 'get-started' 7 | weight: 2 8 | weight: 2 9 | draft: false 10 | --- 11 | 12 | # Basic usage 13 | To easiest way to start with BulmaTagsInput is to add `data-type="tags"` attribute or set `type="tags"` to an input element and call `BulmaTagsInput.attach();` to convert them all into a Tags input control. 14 | 15 | By default Tags input prevent duplicate entries and create selectable and removable tags. These options can be overiden either by JavaScript or by adding options into the input dataset (see [Javascript API](http://10.0.0.6:59626/get-started/javascript-api/) documentation). 16 | {{< preview id="tags-input" lang="html" >}}
17 | 18 |
19 | 20 |
21 |
{{< /preview >}} 22 | 23 | BulmaTagsInput works with `select` element as well. 24 | 25 | _Notice that if `freeInput` option is set to `true` then you can manually type text to search through available values._ 26 | {{< preview id="tags-input-select" lang="html" >}}
27 | 28 |
29 | 33 |
34 |
{{< /preview >}} 35 | 36 | Even with a `multiple` select element: 37 | {{< preview id="tags-input-select-multiple" lang="html" >}}
38 | 39 |
40 | 45 |
46 |
{{< /preview >}} 47 | 48 | ___ 49 | 50 | ## Disabled state 51 | {{< preview id="tags-input-select-disabled" lang="html" >}}
52 | 53 |
54 | 58 |
59 |
{{< /preview >}} 60 | 61 | ## Dynamic data source 62 | Work with dynamic data source to automatically retreive data. 63 | Provide an `Array`, a `Function` or a `Promise` into the `source` option to get dynamic data. 64 | 65 | The following demo helps you find a country using free [REST Countries API](https://restcountries.eu/#api-endpoints-all). 66 | {{< preview id="tags-input-source" lang="html" >}}
67 | 68 |
69 | 70 |
71 |
72 | {{< /preview >}} 87 | 88 | ___ 89 | 90 | ## Do not close dropdown at select 91 | Prevent dropdown to close after selecting an item by setting `closeDropdownOnItemSelect` option to `false`. _(default value: true)_ 92 | {{< preview id="tags-input-select-dont-close" lang="html" >}}
93 | 94 |
95 | 99 |
100 |
{{< /preview >}} 101 | 102 | ___ 103 | 104 | ## Remove free input 105 | Remove free input by setting `freeInput` option to `false`. _(default value: true - automatically set to false on select based element)_ 106 | {{< preview id="tags-input-select" lang="html" >}}
107 | 108 |
109 | 110 |
111 |
{{< /preview >}} 112 | 113 | ___ 114 | 115 | ## Allow duplicates tags 116 | Set `allowDuplicates` to `true` to accept duplicate tags. _(default value: false)_ 117 | {{< preview id="tags-input-select-multiple" lang="html" >}}
118 | 119 |
120 | 124 |
125 |
{{< /preview >}} 126 | 127 | ___ 128 | 129 | ## No removable tags 130 | Set `removable` option to `false` to make non removable tags. _(default value: true)_ 131 | 132 | Options can be passed through [dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset) 133 | {{< preview lang="html" >}}
134 | 135 |
136 | 137 |
138 |
{{< /preview >}} 139 | 140 | ___ 141 | 142 | ## No selectable tags 143 | Set `selectable` option to `false` to make non selectable tags. _(default value: true)_ 144 | {{< preview id="non-selectable" lang="html" >}}
145 | 146 |
147 | 148 |
149 |
{{< /preview >}} 150 | 151 | ___ 152 | 153 | ## Limit number of tags 154 | Set maximum number of tags allowed with the `maxTags` option. _(default value: undefined)_ 155 | 156 | Try adding 2 more tags in the following example. 157 | {{< preview id="limit" lang="html" >}}
158 | 159 |
160 | 161 |
162 |
{{< /preview >}} 163 | 164 | ___ 165 | 166 | ## Characters limit for tags 167 | Set maximum number of characters allowed for each tags with the `minChars` and `maxChars` option. _(default value: 1 | undefined)_ 168 | 169 | Try adding tags with less than 3 characteres or more than 5 characters in the following example. 170 | {{< preview id="limit-characters" lang="html" >}}
171 | 172 |
173 | 174 |
175 |
{{< /preview >}} 176 | 177 | ___ 178 | 179 | ## Object Tags 180 | Use objects as tags instead of simple string. This makes it possible to set id values in your input field's value, instead of just the tag's text. 181 | 182 | {{% notification warning %}}Warning: It is not possible to add tag by typing in this mode (only programmatically or using providing a data source).{{% /notification %}} 183 | {{< preview id="object-tags" lang="html" >}}
184 | 185 |
186 | 187 |
188 |
189 | 200 | 201 |
202 |
203 | 204 |
205 | 209 |
210 |
{{< /preview >}} 211 | -------------------------------------------------------------------------------- /docs/changelog/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changelog - BulmaTagsInput 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 106 |
107 | 128 | 129 |
130 |
131 |

Changelog

132 | 133 |
134 |
135 |

136 | v1.0.2 (2020-05-15) 137 |

138 | 139 |
140 |

Important fixes for select based TagsInput

141 | 193 | 194 |
195 |
196 |
197 | 198 |
199 |
200 |

201 | v1.0.1 (2020-05-07) 202 |

203 | 204 |
205 |

Important fix for Form data

206 |
    207 |
  • 208 | 209 | 210 | 211 | 212 | fixed 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | Duplicate form data when submitting
  • 232 |
233 | 234 |
235 |
236 |
237 | 238 |
239 |
240 |

241 | v1.0.0 (2020-05-02) 242 |

243 | 244 |
245 |

First working version

246 |
    247 |
  • 248 | 249 | 250 | added 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | Works with Input, Select, Multiple Select elements
  • 262 |
  • 263 | 264 | 265 | added 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | Customize behavior with lots of options
  • 277 |
  • 278 | 279 | 280 | added 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | Events API
  • 292 |
  • 293 | 294 | 295 | added 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | External data source management
  • 307 |
  • 308 | 309 | 310 | added 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | Filtering/Search
  • 322 |
323 | 324 |
325 |
326 |
327 | 328 | 329 | 330 |
331 |
332 |
333 |
334 |
335 | 336 | 337 | 338 | 339 | 344 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const internalIp = require('internal-ip'); 3 | const package = require('./package.json'); 4 | const path = require('path'); 5 | const shell = require('gulp-shell'); 6 | 7 | /** 8 | * Template for banner to add to file headers 9 | */ 10 | var banner = { 11 | main: 12 | '/*!' + 13 | ' <%= package.name %> v<%= package.version %>' + 14 | ' | (c) ' + new Date().getFullYear() + ' <%= package.author.name %>' + 15 | ' | <%= package.license %> License' + 16 | ' | <%= package.homepage %>' + 17 | ' */\n' 18 | }; 19 | 20 | /** 21 | * ---------------------------------------- 22 | * SCRIPTS TASKS 23 | * ---------------------------------------- 24 | */ 25 | gulp.task('scripts:build', function(done) { 26 | const cleanDir = require('gulp-clean-dir'); 27 | const fs = require('fs'); 28 | const header = require('gulp-header'); 29 | const nop = require('gulp-nop'); 30 | const parsePath = require('parse-filepath'); 31 | const rename = require("gulp-rename"); 32 | const webpack = require('webpack-stream'); 33 | 34 | distPath = parsePath(package.script); 35 | 36 | if (fs.existsSync(path.resolve(__dirname, 'src/js/index.js'))) { 37 | return gulp.src(path.resolve(__dirname, 'src/js/index.js')) 38 | .pipe(webpack(require('./webpack.config.js'))) 39 | .pipe(header(banner.main, {package: package})) 40 | .pipe(rename(distPath.basename.replace('.min', ''))) 41 | .pipe(cleanDir(path.resolve(__dirname, distPath.dirname))) 42 | .pipe(gulp.dest(path.resolve(__dirname, distPath.dirname))); 43 | } else { 44 | return gulp.src('.').pipe(nop()); 45 | } 46 | }); 47 | 48 | gulp.task('scripts:minify', function(done) { 49 | const header = require('gulp-header'); 50 | const parsePath = require('parse-filepath'); 51 | const rename = require("gulp-rename"); 52 | const terser = require('gulp-terser'); 53 | 54 | distPath = parsePath(package.script); 55 | 56 | return gulp.src([path.resolve(__dirname, distPath.dirname + '/*.js'), '!' + path.resolve(__dirname, distPath.dirname + '/*.min.js')]) 57 | .pipe(terser({ 58 | compress: true, 59 | keep_fnames: true, 60 | ie8: false, 61 | mangle: true, 62 | output: { 63 | comments: false 64 | } 65 | })) 66 | .pipe(header(banner.main, {package: package})) 67 | .pipe(rename({ 68 | suffix: '.min' 69 | })) 70 | .pipe(gulp.dest(path.resolve(__dirname, distPath.dirname))); 71 | }); 72 | 73 | gulp.task('scripts:copy', function() { 74 | const fs = require('fs'); 75 | const gulpif = require('gulp-if'); 76 | const parsePath = require('parse-filepath'); 77 | 78 | distPath = parsePath(package.script); 79 | 80 | return gulp.src(distPath.dirname + '/*.js') 81 | .pipe(gulp.dest(path.resolve(__dirname, 'src/docs/static/js'))) 82 | .pipe(gulpif(fs.existsSync(path.resolve(__dirname, 'src/demo')), gulp.dest(path.resolve(__dirname, 'src/demo/static/js')))); 83 | }); 84 | 85 | /** 86 | * ---------------------------------------- 87 | * STYLESHEETS TASKS 88 | * ---------------------------------------- 89 | */ 90 | gulp.task('styles:build', function() { 91 | const autoprefixer = require('autoprefixer'); 92 | const cleanDir = require('gulp-clean-dir'); 93 | const concat = require('gulp-concat'); 94 | const fs = require('fs'); 95 | const header = require('gulp-header'); 96 | const nop = require('gulp-nop'); 97 | const parsePath = require('parse-filepath'); 98 | const postcss = require('gulp-postcss'); 99 | const rename = require("gulp-rename"); 100 | const sass = require('gulp-sass'); 101 | 102 | distPath = parsePath(package.style); 103 | 104 | if (fs.existsSync(path.resolve(__dirname, 'src/sass/index.sass'))) { 105 | return gulp.src(['node_modules/bulma/sass/utilities/_all.sass', 'node_modules/bulma/sass/form/shared.sass', 'node_modules/bulma/sass/components/dropdown.sass', 'src/sass/index.sass']) 106 | .pipe(concat('app.sass')) 107 | .pipe(sass({ 108 | loadPath: [path.resolve(__dirname, 'src/sass')], 109 | includePaths: ['node_modules', 'node_modules/bulma/sass/utilities/'], 110 | outputStyle: "expanded", 111 | sourceComments: true 112 | }).on('error', sass.logError)) 113 | .pipe(postcss([ 114 | autoprefixer({ 115 | cascade: true, 116 | remove: true 117 | }) 118 | ])) 119 | .pipe(header(banner.main, {package: package})) 120 | .pipe(rename(distPath.basename.replace('.min', ''))) 121 | .pipe(cleanDir(path.resolve(__dirname, distPath.dirname))) 122 | .pipe(gulp.dest(path.resolve(__dirname, distPath.dirname))); 123 | } else { 124 | return gulp.src('.').pipe(nop()); 125 | } 126 | }); 127 | 128 | gulp.task('styles:minify', function() { 129 | const cleancss = require('gulp-cleancss'); 130 | const cssnano = require('cssnano'); 131 | const header = require('gulp-header'); 132 | const parsePath = require('parse-filepath'); 133 | const postcss = require('gulp-postcss'); 134 | const rename = require("gulp-rename"); 135 | 136 | distPath = parsePath(package.style); 137 | 138 | return gulp.src([path.resolve(__dirname, distPath.dirname + '/*.css'), '!' + path.resolve(__dirname, distPath.dirname + '/*.min.css')]) 139 | .pipe(cleancss()) 140 | .pipe(postcss([ 141 | cssnano({ 142 | discardComments: { 143 | removeAll: true 144 | } 145 | }) 146 | ])) 147 | .pipe(header(banner.main, {package: package})) 148 | .pipe(rename({ 149 | suffix: '.min' 150 | })) 151 | .pipe(gulp.dest(path.resolve(__dirname, distPath.dirname))); 152 | }); 153 | 154 | gulp.task('styles:copy', function() { 155 | const fs = require('fs'); 156 | const gulpif = require('gulp-if'); 157 | const parsePath = require('parse-filepath'); 158 | 159 | distPath = parsePath(package.style); 160 | 161 | return gulp.src(path.resolve(__dirname, distPath.dirname + '/*.css')) 162 | .pipe(gulp.dest(path.resolve(__dirname, 'src/docs/static/css'))) 163 | .pipe(gulpif(fs.existsSync(path.resolve(__dirname, 'src/demo')), gulp.dest(path.resolve(__dirname, 'src/demo/static/css')))); 164 | }); 165 | 166 | /** 167 | * ---------------------------------------- 168 | * ASSETS TASKS 169 | * ---------------------------------------- 170 | */ 171 | gulp.task('images:svg:minify', function() { 172 | const svgmin = require('gulp-svgmin'); 173 | 174 | return gulp.src(path.resolve(__dirname, 'dist/images/**/*.svg')) 175 | .pipe(svgmin()) 176 | .pipe(gulp.dest(path.resolve(__dirname, 'dist/images'))); 177 | }); 178 | 179 | /** 180 | * ---------------------------------------- 181 | * BUILD TASKS 182 | * ---------------------------------------- 183 | */ 184 | gulp.task('build:styles', gulp.series('styles:build', 'styles:minify', 'styles:copy'), done => { 185 | done(); 186 | }); 187 | 188 | gulp.task('build:scripts', gulp.series('scripts:build', 'scripts:minify', 'scripts:copy'), done => { 189 | done(); 190 | }); 191 | 192 | gulp.task('build', gulp.series('build:styles', 'build:scripts'), done => { 193 | done(); 194 | }); 195 | 196 | gulp.task('optimize', gulp.series('scripts:minify', 'styles:minify', 'images:svg:minify'), done => { 197 | done(); 198 | }); 199 | 200 | gulp.task('default', gulp.series('build', 'optimize'), done => { 201 | done(); 202 | }); 203 | 204 | /** 205 | * ---------------------------------------- 206 | * DEMO TASKS 207 | * ---------------------------------------- 208 | */ 209 | gulp.task('demo:build', gulp.series(shell.task(['node_modules/.bin/hugo --source src/demo --destination ../../demo --cleanDestinationDir'])), done => { 210 | done(); 211 | }); 212 | 213 | gulp.task('demo:serve', gulp.parallel(shell.task([`node_modules/.bin/hugo server -D --bind ${internalIp.v4.sync()} --baseURL ${internalIp.v4.sync()} --source src/demo --watch`]), function() { 214 | gulp.watch(path.resolve(__dirname, 'src/sass/**/*.sass'), gulp.series('build:styles')); 215 | gulp.watch(path.resolve(__dirname, 'src/js/**/*.js'), gulp.series('build:scripts')); 216 | }), done => { 217 | done(); 218 | }); 219 | 220 | gulp.task('demo', gulp.series(shell.task(['node_modules/.bin/hugo server --source src/demo'])), done => { 221 | done(); 222 | }); 223 | 224 | /** 225 | * ---------------------------------------- 226 | * DOC TASKS 227 | * ---------------------------------------- 228 | */ 229 | gulp.task('doc:build', gulp.series(shell.task(['node_modules/.bin/hugo --source src/docs --destination ../../docs --cleanDestinationDir'])), done => { 230 | done(); 231 | }); 232 | 233 | gulp.task('doc:serve', gulp.parallel(shell.task([`node_modules/.bin/hugo server -D --bind ${internalIp.v4.sync()} --baseURL ${internalIp.v4.sync()} --source src/docs --watch`]), function() { 234 | gulp.watch(path.resolve(__dirname, 'src/sass/**/*.sass'), gulp.series('build:styles')); 235 | gulp.watch(path.resolve(__dirname, 'src/js/**/*.js'), gulp.series('build:scripts')); 236 | }), done => { 237 | done(); 238 | }); 239 | 240 | gulp.task('doc', gulp.series(shell.task(['node_modules/.bin/hugo server --source src/docs'])), done => { 241 | done(); 242 | }); -------------------------------------------------------------------------------- /docs/js/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v2.0.4 3 | * https://zenorocha.github.io/clipboard.js 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n