├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── dist ├── css │ └── selectize.bootstrap4.css ├── examples.html └── js │ └── selectize.js ├── docs └── en │ └── index.md ├── gulpfile.js ├── package-lock.json ├── package.json ├── scss ├── _mixins.scss ├── _variables.scss └── selectize.bootstrap4.scss └── template └── examples.pug /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /node_modules/ 3 | /vendor/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Selectize Theme for Bootstrap 4 2 | 3 | [Selectize](https://selectize.github.io/selectize.js/) Theme (SCSS) based on the [Bootstrap 4](https://getbootstrap.com/) components. 4 | 5 | ## Table of Contents 6 | 7 | - [Status](#status) 8 | - [Quick Start](#quick-start) 9 | - [TODO](#todo) 10 | - [Creators](#creators) 11 | - [Copyrights and License](#copyrights-and-license) 12 | 13 | ## Status 14 | 15 | [![GitHub release](https://img.shields.io/github/release/const-se/selectize-bootstrap4-theme.svg)](https://github.com/const-se/selectize-bootstrap4-theme/releases) 16 | [![npm version](https://img.shields.io/npm/v/selectize-bootstrap4-theme.svg)](https://www.npmjs.com/package/selectize-bootstrap4-theme) 17 | [![Packagist](https://img.shields.io/packagist/v/const-se/selectize-bootstrap4-theme.svg)](https://packagist.org/packages/const-se/selectize-bootstrap4-theme) 18 | [![Github file size](https://img.shields.io/github/size/const-se/selectize-bootstrap4-theme/dist/css/selectize.bootstrap4.css.svg)](https://github.com/const-se/selectize-bootstrap4-theme/blob/master/dist/css/selectize.bootstrap4.css) 19 | [![Github All Releases](https://img.shields.io/github/downloads/const-se/selectize-bootstrap4-theme/total.svg)](https://github.com/const-se/selectize-bootstrap4-theme) 20 | [![npm](https://img.shields.io/npm/dt/selectize-bootstrap4-theme.svg)](https://www.npmjs.com/package/selectize-bootstrap4-theme) 21 | [![Packagist](https://img.shields.io/packagist/dt/const-se/selectize-bootstrap4-theme.svg)](https://packagist.org/packages/const-se/selectize-bootstrap4-theme) 22 | 23 | ## Quick Start 24 | 25 | Several quick start options are available: 26 | 27 | - [Download the latest release](https://github.com/const-se/selectize-bootstrap4-theme/archive/v2.0.2.zip) 28 | - Clone the repo: `git clone git@github.com:const-se/selectize-bootstrap4-theme.git` 29 | - Install with [npm](https://www.npmjs.com/): `npm install selectize-bootstrap4-theme` 30 | - Install with [yarn](https://yarnpkg.com/): `yarn add selectize-bootstrap4-theme` 31 | - Install with [composer](https://getcomposer.org/): `composer require const-se/selectize-bootstrap4-theme` 32 | 33 | Read the [Documentation](docs/en/index.md) for more information. 34 | 35 | ## TODO 36 | 37 | - Attribute `readonly` support 38 | - Pseudo-classes `:valid`, `:invalid` support 39 | - Bootstrap class `custom-select` support 40 | - Selectize plugin styles support 41 | 42 | ## Creators 43 | 44 | **Constantine Seleznyoff** 45 | 46 | - const.seoff@gmail.com 47 | 48 | ## Copyrights and License 49 | 50 | Copyright 2018 [Constantine Seleznyoff](https://github.com/const-se). 51 | Code released under the [Apache 2.0 License](https://github.com/const-se/selectize-bootstrap4-theme/blob/master/LICENSE). 52 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "const-se/selectize-bootstrap4-theme", 3 | "type": "library", 4 | "version": "2.0.2", 5 | "license": "Apache-2.0", 6 | "description": "Selectize Theme for Bootstrap 4", 7 | "keywords": [ 8 | "bootstrap", 9 | "bootstrap4", 10 | "css", 11 | "sass", 12 | "scss", 13 | "select", 14 | "selectize", 15 | "theme", 16 | "web" 17 | ], 18 | "authors": [ 19 | { 20 | "name": "Constantine Seleznyoff", 21 | "email": "const.seoff@gmail.com" 22 | } 23 | ], 24 | "homepage": "https://github.com/const-se/selectize-bootstrap4-theme", 25 | "extra": { 26 | "branch-alias": { 27 | "dev-master": "2.0.x-dev" 28 | } 29 | }, 30 | "support": { 31 | "email": "const.seoff@gmail.com", 32 | "issues": "https://github.com/const-se/selectize-bootstrap4-theme/issues" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dist/css/selectize.bootstrap4.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Selectize Theme for Bootstrap 4 v2.0.2 3 | * 4 | * Copyright 2018 Constantine Seleznyoff 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | .form-control.selectize-control { 19 | background-color: transparent; 20 | border: none; 21 | border-radius: 0; 22 | box-shadow: none; 23 | height: calc(2.25rem + 2px); 24 | padding: 0; 25 | position: relative; 26 | transition: none; 27 | } 28 | 29 | .form-control.selectize-control .selectize-input { 30 | background-clip: padding-box; 31 | background-color: #fff; 32 | border: 1px solid #ced4da; 33 | color: #495057; 34 | cursor: text; 35 | display: inline-block; 36 | font-size: 1rem; 37 | height: 100%; 38 | overflow: hidden; 39 | padding: 0.375rem 0.75rem; 40 | position: relative; 41 | width: 100%; 42 | border-radius: 0.25rem; 43 | transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; 44 | } 45 | 46 | @media screen and (prefers-reduced-motion: reduce) { 47 | .form-control.selectize-control .selectize-input { 48 | transition: none; 49 | } 50 | } 51 | 52 | .form-control.selectize-control .selectize-input * { 53 | display: -moz-inline-stack; 54 | display: inline-block; 55 | *display: inline; 56 | zoom: 1; 57 | vertical-align: baseline; 58 | } 59 | 60 | .form-control.selectize-control .selectize-input input { 61 | background: none !important; 62 | border: none !important; 63 | box-shadow: none !important; 64 | color: inherit; 65 | display: inline-block !important; 66 | font-size: inherit; 67 | line-height: inherit !important; 68 | margin: 0 2px 0 0 !important; 69 | max-height: none !important; 70 | max-width: 100% !important; 71 | min-height: 0 !important; 72 | padding: 0 !important; 73 | text-indent: 0 !important; 74 | -webkit-user-select: auto !important; 75 | } 76 | 77 | .form-control.selectize-control .selectize-input input:hover, .form-control.selectize-control .selectize-input input:focus { 78 | outline: none !important; 79 | } 80 | 81 | .form-control.selectize-control .selectize-input input::-ms-clear { 82 | display: none; 83 | } 84 | 85 | .form-control.selectize-control .selectize-input input::placeholder { 86 | color: #6c757d; 87 | opacity: 1; 88 | } 89 | 90 | .form-control.selectize-control .selectize-input.focus { 91 | color: #495057; 92 | background-color: #fff; 93 | border-color: #80bdff; 94 | outline: 0; 95 | box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); 96 | } 97 | 98 | .form-control.selectize-control .selectize-input.disabled { 99 | background-color: #e9ecef; 100 | color: #495057; 101 | opacity: 1; 102 | } 103 | 104 | .form-control.selectize-control .selectize-input.dropdown-active { 105 | border-bottom-right-radius: 0; 106 | border-bottom-left-radius: 0; 107 | } 108 | 109 | .form-control.selectize-control .selectize-dropdown { 110 | background-color: transparent; 111 | border: none; 112 | border-radius: 0; 113 | box-shadow: none; 114 | display: none; 115 | height: auto; 116 | left: 0; 117 | margin: 0 !important; 118 | padding: 0; 119 | position: absolute; 120 | top: 100%; 121 | transition: none; 122 | width: 100% !important; 123 | z-index: 1000; 124 | } 125 | 126 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content { 127 | background-color: #fff; 128 | background-clip: padding-box; 129 | border: 1px solid #ced4da; 130 | border-radius: 0 0 0.25rem 0.25rem; 131 | border-top-width: 0; 132 | color: #212529; 133 | font-size: 1rem; 134 | max-height: 14.5rem; 135 | overflow-x: hidden; 136 | overflow-y: auto; 137 | padding: 0.5rem 0; 138 | position: relative; 139 | text-align: left; 140 | -webkit-overflow-scrolling: touch; 141 | } 142 | 143 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option, 144 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .create { 145 | background-color: transparent; 146 | color: #212529; 147 | font-weight: 400; 148 | padding: 0.25rem 1.5rem; 149 | text-align: inherit; 150 | white-space: nowrap; 151 | } 152 | 153 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .create { 154 | cursor: pointer; 155 | } 156 | 157 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option:hover, .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option:focus { 158 | color: #fff; 159 | text-decoration: none; 160 | background-color: #007bff; 161 | } 162 | 163 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option.active, .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option:active { 164 | color: #fff; 165 | text-decoration: none; 166 | background-color: #007bff; 167 | } 168 | 169 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option.disabled, .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option:disabled, .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option[data-disabled] { 170 | background-color: transparent; 171 | color: #6c757d; 172 | } 173 | 174 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .option[data-selectable] { 175 | cursor: pointer; 176 | overflow: hidden; 177 | } 178 | 179 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .optgroup { 180 | border-bottom: 1px solid #e9ecef; 181 | margin-bottom: 0.5rem; 182 | padding-bottom: 0.5rem; 183 | } 184 | 185 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .optgroup:last-child { 186 | border-bottom-width: 0; 187 | margin-bottom: 0; 188 | padding-bottom: 0; 189 | } 190 | 191 | .form-control.selectize-control .selectize-dropdown .selectize-dropdown-content .optgroup .optgroup-header { 192 | color: #6c757d; 193 | display: block; 194 | font-size: 0.875rem; 195 | margin-bottom: 0; 196 | padding: 0.25rem 1.5rem; 197 | white-space: nowrap; 198 | } 199 | 200 | .form-control.selectize-control.single:after { 201 | border-color: #212529 transparent transparent transparent; 202 | border-style: solid; 203 | border-width: 0.54127rem 0.3125rem 0 0.3125rem; 204 | content: ''; 205 | display: block; 206 | height: 0; 207 | margin-top: -0.27063rem; 208 | position: absolute; 209 | top: 50%; 210 | right: 0.75rem; 211 | width: 0; 212 | } 213 | 214 | .form-control.selectize-control.single .selectize-input { 215 | padding-right: calc(0.75rem + 0.625rem + 0.375rem); 216 | } 217 | 218 | .form-control.selectize-control.multi { 219 | height: auto; 220 | min-height: calc(2.25rem + 2px); 221 | } 222 | 223 | .form-control.selectize-control.multi .selectize-input { 224 | height: auto; 225 | min-height: 100%; 226 | overflow: auto; 227 | } 228 | 229 | .form-control.selectize-control.multi .selectize-input .item { 230 | margin: 0 3px 0 0; 231 | } 232 | 233 | .form-control.selectize-control .selectize-dropdown-content .create strong, 234 | .form-control.selectize-control.multi .selectize-input .item { 235 | background-color: #007bff; 236 | color: #fff; 237 | display: inline-block; 238 | font-size: 75%; 239 | font-weight: 400; 240 | line-height: 1; 241 | padding: 0.25em 0.4em; 242 | text-align: center; 243 | vertical-align: middle; 244 | white-space: nowrap; 245 | border-radius: 0.25rem; 246 | } 247 | 248 | .form-control.selectize-control.rtl { 249 | direction: rtl; 250 | } 251 | 252 | .form-control.selectize-control.rtl .selectize-input { 253 | text-align: right; 254 | } 255 | 256 | .form-control.selectize-control.rtl .selectize-input input { 257 | margin: 0 0 0 2px !important; 258 | } 259 | 260 | .form-control.selectize-control.rtl .selectize-dropdown .selectize-dropdown-content { 261 | text-align: right !important; 262 | } 263 | 264 | .form-control.selectize-control.rtl.single:after { 265 | left: 0.75rem; 266 | right: auto; 267 | } 268 | 269 | .form-control.selectize-control.rtl.single .selectize-input { 270 | padding-left: calc(0.75rem + 0.625rem + 0.375rem); 271 | padding-right: 0.75rem; 272 | } 273 | 274 | .form-control.selectize-control.rtl.multi .selectize-input .item { 275 | margin: 0 0 0 3px; 276 | } 277 | 278 | .form-control.selectize-control.is-valid .selectize-input { 279 | border-color: #28a745; 280 | } 281 | 282 | .form-control.selectize-control.is-valid .selectize-input:focus { 283 | border-color: #28a745; 284 | box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); 285 | } 286 | 287 | .form-control.selectize-control.is-invalid .selectize-input { 288 | border-color: #dc3545; 289 | } 290 | 291 | .form-control.selectize-control.is-invalid .selectize-input:focus { 292 | border-color: #dc3545; 293 | box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); 294 | } 295 | 296 | .form-control-lg.selectize-control { 297 | height: calc(2.875rem + 2px); 298 | padding: 0; 299 | } 300 | 301 | .form-control-lg.selectize-control .selectize-input { 302 | font-size: 1.25rem; 303 | padding: 0.5rem 1rem; 304 | border-radius: 0.3rem; 305 | } 306 | 307 | .form-control-lg.selectize-control.single .selectize-input { 308 | padding-right: calc(1rem + 0.625rem + 0.5rem); 309 | } 310 | 311 | .form-control-lg.selectize-control.single.rtl .selectize-input { 312 | padding-left: calc(1rem + 0.625rem + 0.5rem); 313 | padding-right: 1rem; 314 | } 315 | 316 | .form-control-lg.selectize-control.multi { 317 | min-height: calc(2.875rem + 2px); 318 | } 319 | 320 | .form-control-sm.selectize-control { 321 | height: calc(1.8125rem + 2px); 322 | padding: 0; 323 | } 324 | 325 | .form-control-sm.selectize-control .selectize-input { 326 | font-size: 0.875rem; 327 | padding: 0.25rem 0.5rem; 328 | border-radius: 0.2rem; 329 | } 330 | 331 | .form-control-sm.selectize-control.single .selectize-input { 332 | padding-right: calc(0.5rem + 0.625rem + 0.25rem); 333 | } 334 | 335 | .form-control-sm.selectize-control.single.rtl .selectize-input { 336 | padding-left: calc(0.5rem + 0.625rem + 0.25rem); 337 | padding-right: 0.5rem; 338 | } 339 | 340 | .form-control-sm.selectize-control.multi { 341 | min-height: calc(1.8125rem + 2px); 342 | } 343 | 344 | .input-group > .form-control.selectize-control.multi { 345 | height: calc(2.25rem + 2px); 346 | } 347 | 348 | .input-group > .form-control:not(:first-child).selectize-control .selectize-input { 349 | border-top-left-radius: 0; 350 | border-bottom-left-radius: 0; 351 | } 352 | 353 | .input-group > .form-control:not(:last-child).selectize-control .selectize-input { 354 | border-top-right-radius: 0; 355 | border-bottom-right-radius: 0; 356 | } 357 | -------------------------------------------------------------------------------- /dist/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Selectize Theme for Bootstrap 4 6 | 7 | 8 | 9 | 10 |
11 |

Selectize Theme for Bootstrap 4

12 |
13 |
14 |

Single Select

15 |
16 |
17 | 18 | 31 |
32 |
33 | 34 | 47 |
48 |
49 | 50 | 63 |
64 |
65 | 66 | 79 |
80 |
81 | 82 | 98 |
99 |
100 | 101 | 104 |
Looks good!
105 |
106 |
107 | 108 | 111 |
Please provide valid color.
112 |
113 |
114 |
115 | 116 | 129 |
130 |
131 | 132 |
133 |
134 |
Color
135 |
136 | 149 |
150 |
!
151 |
152 |
153 |
154 |
155 |
156 |

Multiple Select

157 |
158 |
159 | 160 | 165 |
166 |
167 | 168 | 173 |
174 |
175 | 176 | 181 |
182 |
183 | 184 | 189 |
190 |
191 | 192 | 193 |
194 |
195 | 196 | 199 |
Looks good!
200 |
201 |
202 | 203 | 206 |
Please provide valid color.
207 |
208 |
209 |
210 | 211 | 216 |
217 |
218 | 219 |
220 |
221 |
Color
222 |
223 | 228 |
229 |
!
230 |
231 |
232 |
233 |
234 |
235 |
236 | 237 | 238 | 302 | 303 | -------------------------------------------------------------------------------- /dist/js/selectize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * sifter.js 3 | * Copyright (c) 2013 Brian Reavis & contributors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 6 | * file except in compliance with the License. You may obtain a copy of the License at: 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under 10 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | * ANY KIND, either express or implied. See the License for the specific language 12 | * governing permissions and limitations under the License. 13 | * 14 | * @author Brian Reavis 15 | */ 16 | 17 | (function(root, factory) { 18 | if (typeof define === 'function' && define.amd) { 19 | define('sifter', factory); 20 | } else if (typeof exports === 'object') { 21 | module.exports = factory(); 22 | } else { 23 | root.Sifter = factory(); 24 | } 25 | }(this, function() { 26 | 27 | /** 28 | * Textually searches arrays and hashes of objects 29 | * by property (or multiple properties). Designed 30 | * specifically for autocomplete. 31 | * 32 | * @constructor 33 | * @param {array|object} items 34 | * @param {object} items 35 | */ 36 | var Sifter = function(items, settings) { 37 | this.items = items; 38 | this.settings = settings || {diacritics: true}; 39 | }; 40 | 41 | /** 42 | * Splits a search string into an array of individual 43 | * regexps to be used to match results. 44 | * 45 | * @param {string} query 46 | * @returns {array} 47 | */ 48 | Sifter.prototype.tokenize = function(query) { 49 | query = trim(String(query || '').toLowerCase()); 50 | if (!query || !query.length) return []; 51 | 52 | var i, n, regex, letter; 53 | var tokens = []; 54 | var words = query.split(/ +/); 55 | 56 | for (i = 0, n = words.length; i < n; i++) { 57 | regex = escape_regex(words[i]); 58 | if (this.settings.diacritics) { 59 | for (letter in DIACRITICS) { 60 | if (DIACRITICS.hasOwnProperty(letter)) { 61 | regex = regex.replace(new RegExp(letter, 'g'), DIACRITICS[letter]); 62 | } 63 | } 64 | } 65 | tokens.push({ 66 | string : words[i], 67 | regex : new RegExp(regex, 'i') 68 | }); 69 | } 70 | 71 | return tokens; 72 | }; 73 | 74 | /** 75 | * Iterates over arrays and hashes. 76 | * 77 | * ``` 78 | * this.iterator(this.items, function(item, id) { 79 | * // invoked for each item 80 | * }); 81 | * ``` 82 | * 83 | * @param {array|object} object 84 | */ 85 | Sifter.prototype.iterator = function(object, callback) { 86 | var iterator; 87 | if (is_array(object)) { 88 | iterator = Array.prototype.forEach || function(callback) { 89 | for (var i = 0, n = this.length; i < n; i++) { 90 | callback(this[i], i, this); 91 | } 92 | }; 93 | } else { 94 | iterator = function(callback) { 95 | for (var key in this) { 96 | if (this.hasOwnProperty(key)) { 97 | callback(this[key], key, this); 98 | } 99 | } 100 | }; 101 | } 102 | 103 | iterator.apply(object, [callback]); 104 | }; 105 | 106 | /** 107 | * Returns a function to be used to score individual results. 108 | * 109 | * Good matches will have a higher score than poor matches. 110 | * If an item is not a match, 0 will be returned by the function. 111 | * 112 | * @param {object|string} search 113 | * @param {object} options (optional) 114 | * @returns {function} 115 | */ 116 | Sifter.prototype.getScoreFunction = function(search, options) { 117 | var self, fields, tokens, token_count, nesting; 118 | 119 | self = this; 120 | search = self.prepareSearch(search, options); 121 | tokens = search.tokens; 122 | fields = search.options.fields; 123 | token_count = tokens.length; 124 | nesting = search.options.nesting; 125 | 126 | /** 127 | * Calculates how close of a match the 128 | * given value is against a search token. 129 | * 130 | * @param {mixed} value 131 | * @param {object} token 132 | * @return {number} 133 | */ 134 | var scoreValue = function(value, token) { 135 | var score, pos; 136 | 137 | if (!value) return 0; 138 | value = String(value || ''); 139 | pos = value.search(token.regex); 140 | if (pos === -1) return 0; 141 | score = token.string.length / value.length; 142 | if (pos === 0) score += 0.5; 143 | return score; 144 | }; 145 | 146 | /** 147 | * Calculates the score of an object 148 | * against the search query. 149 | * 150 | * @param {object} token 151 | * @param {object} data 152 | * @return {number} 153 | */ 154 | var scoreObject = (function() { 155 | var field_count = fields.length; 156 | if (!field_count) { 157 | return function() { return 0; }; 158 | } 159 | if (field_count === 1) { 160 | return function(token, data) { 161 | return scoreValue(getattr(data, fields[0], nesting), token); 162 | }; 163 | } 164 | return function(token, data) { 165 | for (var i = 0, sum = 0; i < field_count; i++) { 166 | sum += scoreValue(getattr(data, fields[i], nesting), token); 167 | } 168 | return sum / field_count; 169 | }; 170 | })(); 171 | 172 | if (!token_count) { 173 | return function() { return 0; }; 174 | } 175 | if (token_count === 1) { 176 | return function(data) { 177 | return scoreObject(tokens[0], data); 178 | }; 179 | } 180 | 181 | if (search.options.conjunction === 'and') { 182 | return function(data) { 183 | var score; 184 | for (var i = 0, sum = 0; i < token_count; i++) { 185 | score = scoreObject(tokens[i], data); 186 | if (score <= 0) return 0; 187 | sum += score; 188 | } 189 | return sum / token_count; 190 | }; 191 | } else { 192 | return function(data) { 193 | for (var i = 0, sum = 0; i < token_count; i++) { 194 | sum += scoreObject(tokens[i], data); 195 | } 196 | return sum / token_count; 197 | }; 198 | } 199 | }; 200 | 201 | /** 202 | * Returns a function that can be used to compare two 203 | * results, for sorting purposes. If no sorting should 204 | * be performed, `null` will be returned. 205 | * 206 | * @param {string|object} search 207 | * @param {object} options 208 | * @return function(a,b) 209 | */ 210 | Sifter.prototype.getSortFunction = function(search, options) { 211 | var i, n, self, field, fields, fields_count, multiplier, multipliers, get_field, implicit_score, sort; 212 | 213 | self = this; 214 | search = self.prepareSearch(search, options); 215 | sort = (!search.query && options.sort_empty) || options.sort; 216 | 217 | /** 218 | * Fetches the specified sort field value 219 | * from a search result item. 220 | * 221 | * @param {string} name 222 | * @param {object} result 223 | * @return {mixed} 224 | */ 225 | get_field = function(name, result) { 226 | if (name === '$score') return result.score; 227 | return getattr(self.items[result.id], name, options.nesting); 228 | }; 229 | 230 | // parse options 231 | fields = []; 232 | if (sort) { 233 | for (i = 0, n = sort.length; i < n; i++) { 234 | if (search.query || sort[i].field !== '$score') { 235 | fields.push(sort[i]); 236 | } 237 | } 238 | } 239 | 240 | // the "$score" field is implied to be the primary 241 | // sort field, unless it's manually specified 242 | if (search.query) { 243 | implicit_score = true; 244 | for (i = 0, n = fields.length; i < n; i++) { 245 | if (fields[i].field === '$score') { 246 | implicit_score = false; 247 | break; 248 | } 249 | } 250 | if (implicit_score) { 251 | fields.unshift({field: '$score', direction: 'desc'}); 252 | } 253 | } else { 254 | for (i = 0, n = fields.length; i < n; i++) { 255 | if (fields[i].field === '$score') { 256 | fields.splice(i, 1); 257 | break; 258 | } 259 | } 260 | } 261 | 262 | multipliers = []; 263 | for (i = 0, n = fields.length; i < n; i++) { 264 | multipliers.push(fields[i].direction === 'desc' ? -1 : 1); 265 | } 266 | 267 | // build function 268 | fields_count = fields.length; 269 | if (!fields_count) { 270 | return null; 271 | } else if (fields_count === 1) { 272 | field = fields[0].field; 273 | multiplier = multipliers[0]; 274 | return function(a, b) { 275 | return multiplier * cmp( 276 | get_field(field, a), 277 | get_field(field, b) 278 | ); 279 | }; 280 | } else { 281 | return function(a, b) { 282 | var i, result, a_value, b_value, field; 283 | for (i = 0; i < fields_count; i++) { 284 | field = fields[i].field; 285 | result = multipliers[i] * cmp( 286 | get_field(field, a), 287 | get_field(field, b) 288 | ); 289 | if (result) return result; 290 | } 291 | return 0; 292 | }; 293 | } 294 | }; 295 | 296 | /** 297 | * Parses a search query and returns an object 298 | * with tokens and fields ready to be populated 299 | * with results. 300 | * 301 | * @param {string} query 302 | * @param {object} options 303 | * @returns {object} 304 | */ 305 | Sifter.prototype.prepareSearch = function(query, options) { 306 | if (typeof query === 'object') return query; 307 | 308 | options = extend({}, options); 309 | 310 | var option_fields = options.fields; 311 | var option_sort = options.sort; 312 | var option_sort_empty = options.sort_empty; 313 | 314 | if (option_fields && !is_array(option_fields)) options.fields = [option_fields]; 315 | if (option_sort && !is_array(option_sort)) options.sort = [option_sort]; 316 | if (option_sort_empty && !is_array(option_sort_empty)) options.sort_empty = [option_sort_empty]; 317 | 318 | return { 319 | options : options, 320 | query : String(query || '').toLowerCase(), 321 | tokens : this.tokenize(query), 322 | total : 0, 323 | items : [] 324 | }; 325 | }; 326 | 327 | /** 328 | * Searches through all items and returns a sorted array of matches. 329 | * 330 | * The `options` parameter can contain: 331 | * 332 | * - fields {string|array} 333 | * - sort {array} 334 | * - score {function} 335 | * - filter {bool} 336 | * - limit {integer} 337 | * 338 | * Returns an object containing: 339 | * 340 | * - options {object} 341 | * - query {string} 342 | * - tokens {array} 343 | * - total {int} 344 | * - items {array} 345 | * 346 | * @param {string} query 347 | * @param {object} options 348 | * @returns {object} 349 | */ 350 | Sifter.prototype.search = function(query, options) { 351 | var self = this, value, score, search, calculateScore; 352 | var fn_sort; 353 | var fn_score; 354 | 355 | search = this.prepareSearch(query, options); 356 | options = search.options; 357 | query = search.query; 358 | 359 | // generate result scoring function 360 | fn_score = options.score || self.getScoreFunction(search); 361 | 362 | // perform search and sort 363 | if (query.length) { 364 | self.iterator(self.items, function(item, id) { 365 | score = fn_score(item); 366 | if (options.filter === false || score > 0) { 367 | search.items.push({'score': score, 'id': id}); 368 | } 369 | }); 370 | } else { 371 | self.iterator(self.items, function(item, id) { 372 | search.items.push({'score': 1, 'id': id}); 373 | }); 374 | } 375 | 376 | fn_sort = self.getSortFunction(search, options); 377 | if (fn_sort) search.items.sort(fn_sort); 378 | 379 | // apply limits 380 | search.total = search.items.length; 381 | if (typeof options.limit === 'number') { 382 | search.items = search.items.slice(0, options.limit); 383 | } 384 | 385 | return search; 386 | }; 387 | 388 | // utilities 389 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 390 | 391 | var cmp = function(a, b) { 392 | if (typeof a === 'number' && typeof b === 'number') { 393 | return a > b ? 1 : (a < b ? -1 : 0); 394 | } 395 | a = asciifold(String(a || '')); 396 | b = asciifold(String(b || '')); 397 | if (a > b) return 1; 398 | if (b > a) return -1; 399 | return 0; 400 | }; 401 | 402 | var extend = function(a, b) { 403 | var i, n, k, object; 404 | for (i = 1, n = arguments.length; i < n; i++) { 405 | object = arguments[i]; 406 | if (!object) continue; 407 | for (k in object) { 408 | if (object.hasOwnProperty(k)) { 409 | a[k] = object[k]; 410 | } 411 | } 412 | } 413 | return a; 414 | }; 415 | 416 | /** 417 | * A property getter resolving dot-notation 418 | * @param {Object} obj The root object to fetch property on 419 | * @param {String} name The optionally dotted property name to fetch 420 | * @param {Boolean} nesting Handle nesting or not 421 | * @return {Object} The resolved property value 422 | */ 423 | var getattr = function(obj, name, nesting) { 424 | if (!obj || !name) return; 425 | if (!nesting) return obj[name]; 426 | var names = name.split("."); 427 | while(names.length && (obj = obj[names.shift()])); 428 | return obj; 429 | }; 430 | 431 | var trim = function(str) { 432 | return (str + '').replace(/^\s+|\s+$|/g, ''); 433 | }; 434 | 435 | var escape_regex = function(str) { 436 | return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); 437 | }; 438 | 439 | var is_array = Array.isArray || (typeof $ !== 'undefined' && $.isArray) || function(object) { 440 | return Object.prototype.toString.call(object) === '[object Array]'; 441 | }; 442 | 443 | var DIACRITICS = { 444 | 'a': '[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]', 445 | 'b': '[b␢βΒB฿𐌁ᛒ]', 446 | 'c': '[cĆćĈĉČčĊċC̄c̄ÇçḈḉȻȼƇƈɕᴄCc]', 447 | 'd': '[dĎďḊḋḐḑḌḍḒḓḎḏĐđD̦d̦ƉɖƊɗƋƌᵭᶁᶑȡᴅDdð]', 448 | 'e': '[eÉéÈèÊêḘḙĚěĔĕẼẽḚḛẺẻĖėËëĒēȨȩĘęᶒɆɇȄȅẾếỀềỄễỂểḜḝḖḗḔḕȆȇẸẹỆệⱸᴇEeɘǝƏƐε]', 449 | 'f': '[fƑƒḞḟ]', 450 | 'g': '[gɢ₲ǤǥĜĝĞğĢģƓɠĠġ]', 451 | 'h': '[hĤĥĦħḨḩẖẖḤḥḢḣɦʰǶƕ]', 452 | 'i': '[iÍíÌìĬĭÎîǏǐÏïḮḯĨĩĮįĪīỈỉȈȉȊȋỊịḬḭƗɨɨ̆ᵻᶖİiIıɪIi]', 453 | 'j': '[jȷĴĵɈɉʝɟʲ]', 454 | 'k': '[kƘƙꝀꝁḰḱǨǩḲḳḴḵκϰ₭]', 455 | 'l': '[lŁłĽľĻļĹĺḶḷḸḹḼḽḺḻĿŀȽƚⱠⱡⱢɫɬᶅɭȴʟLl]', 456 | 'n': '[nŃńǸǹŇňÑñṄṅŅņṆṇṊṋṈṉN̈n̈ƝɲȠƞᵰᶇɳȵɴNnŊŋ]', 457 | 'o': '[oØøÖöÓóÒòÔôǑǒŐőŎŏȮȯỌọƟɵƠơỎỏŌōÕõǪǫȌȍՕօ]', 458 | 'p': '[pṔṕṖṗⱣᵽƤƥᵱ]', 459 | 'q': '[qꝖꝗʠɊɋꝘꝙq̃]', 460 | 'r': '[rŔŕɌɍŘřŖŗṘṙȐȑȒȓṚṛⱤɽ]', 461 | 's': '[sŚśṠṡṢṣꞨꞩŜŝŠšŞşȘșS̈s̈]', 462 | 't': '[tŤťṪṫŢţṬṭƮʈȚțṰṱṮṯƬƭ]', 463 | 'u': '[uŬŭɄʉỤụÜüÚúÙùÛûǓǔŰűŬŭƯưỦủŪūŨũŲųȔȕ∪]', 464 | 'v': '[vṼṽṾṿƲʋꝞꝟⱱʋ]', 465 | 'w': '[wẂẃẀẁŴŵẄẅẆẇẈẉ]', 466 | 'x': '[xẌẍẊẋχ]', 467 | 'y': '[yÝýỲỳŶŷŸÿỸỹẎẏỴỵɎɏƳƴ]', 468 | 'z': '[zŹźẐẑŽžŻżẒẓẔẕƵƶ]' 469 | }; 470 | 471 | var asciifold = (function() { 472 | var i, n, k, chunk; 473 | var foreignletters = ''; 474 | var lookup = {}; 475 | for (k in DIACRITICS) { 476 | if (DIACRITICS.hasOwnProperty(k)) { 477 | chunk = DIACRITICS[k].substring(2, DIACRITICS[k].length - 1); 478 | foreignletters += chunk; 479 | for (i = 0, n = chunk.length; i < n; i++) { 480 | lookup[chunk.charAt(i)] = k; 481 | } 482 | } 483 | } 484 | var regexp = new RegExp('[' + foreignletters + ']', 'g'); 485 | return function(str) { 486 | return str.replace(regexp, function(foreignletter) { 487 | return lookup[foreignletter]; 488 | }).toLowerCase(); 489 | }; 490 | })(); 491 | 492 | 493 | // export 494 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 495 | 496 | return Sifter; 497 | })); 498 | 499 | 500 | 501 | /** 502 | * microplugin.js 503 | * Copyright (c) 2013 Brian Reavis & contributors 504 | * 505 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 506 | * file except in compliance with the License. You may obtain a copy of the License at: 507 | * http://www.apache.org/licenses/LICENSE-2.0 508 | * 509 | * Unless required by applicable law or agreed to in writing, software distributed under 510 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 511 | * ANY KIND, either express or implied. See the License for the specific language 512 | * governing permissions and limitations under the License. 513 | * 514 | * @author Brian Reavis 515 | */ 516 | 517 | (function(root, factory) { 518 | if (typeof define === 'function' && define.amd) { 519 | define('microplugin', factory); 520 | } else if (typeof exports === 'object') { 521 | module.exports = factory(); 522 | } else { 523 | root.MicroPlugin = factory(); 524 | } 525 | }(this, function() { 526 | var MicroPlugin = {}; 527 | 528 | MicroPlugin.mixin = function(Interface) { 529 | Interface.plugins = {}; 530 | 531 | /** 532 | * Initializes the listed plugins (with options). 533 | * Acceptable formats: 534 | * 535 | * List (without options): 536 | * ['a', 'b', 'c'] 537 | * 538 | * List (with options): 539 | * [{'name': 'a', options: {}}, {'name': 'b', options: {}}] 540 | * 541 | * Hash (with options): 542 | * {'a': { ... }, 'b': { ... }, 'c': { ... }} 543 | * 544 | * @param {mixed} plugins 545 | */ 546 | Interface.prototype.initializePlugins = function(plugins) { 547 | var i, n, key; 548 | var self = this; 549 | var queue = []; 550 | 551 | self.plugins = { 552 | names : [], 553 | settings : {}, 554 | requested : {}, 555 | loaded : {} 556 | }; 557 | 558 | if (utils.isArray(plugins)) { 559 | for (i = 0, n = plugins.length; i < n; i++) { 560 | if (typeof plugins[i] === 'string') { 561 | queue.push(plugins[i]); 562 | } else { 563 | self.plugins.settings[plugins[i].name] = plugins[i].options; 564 | queue.push(plugins[i].name); 565 | } 566 | } 567 | } else if (plugins) { 568 | for (key in plugins) { 569 | if (plugins.hasOwnProperty(key)) { 570 | self.plugins.settings[key] = plugins[key]; 571 | queue.push(key); 572 | } 573 | } 574 | } 575 | 576 | while (queue.length) { 577 | self.require(queue.shift()); 578 | } 579 | }; 580 | 581 | Interface.prototype.loadPlugin = function(name) { 582 | var self = this; 583 | var plugins = self.plugins; 584 | var plugin = Interface.plugins[name]; 585 | 586 | if (!Interface.plugins.hasOwnProperty(name)) { 587 | throw new Error('Unable to find "' + name + '" plugin'); 588 | } 589 | 590 | plugins.requested[name] = true; 591 | plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]); 592 | plugins.names.push(name); 593 | }; 594 | 595 | /** 596 | * Initializes a plugin. 597 | * 598 | * @param {string} name 599 | */ 600 | Interface.prototype.require = function(name) { 601 | var self = this; 602 | var plugins = self.plugins; 603 | 604 | if (!self.plugins.loaded.hasOwnProperty(name)) { 605 | if (plugins.requested[name]) { 606 | throw new Error('Plugin has circular dependency ("' + name + '")'); 607 | } 608 | self.loadPlugin(name); 609 | } 610 | 611 | return plugins.loaded[name]; 612 | }; 613 | 614 | /** 615 | * Registers a plugin. 616 | * 617 | * @param {string} name 618 | * @param {function} fn 619 | */ 620 | Interface.define = function(name, fn) { 621 | Interface.plugins[name] = { 622 | 'name' : name, 623 | 'fn' : fn 624 | }; 625 | }; 626 | }; 627 | 628 | var utils = { 629 | isArray: Array.isArray || function(vArg) { 630 | return Object.prototype.toString.call(vArg) === '[object Array]'; 631 | } 632 | }; 633 | 634 | return MicroPlugin; 635 | })); 636 | 637 | /** 638 | * selectize.js (v0.12.6) 639 | * Copyright (c) 2013–2015 Brian Reavis & contributors 640 | * 641 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 642 | * file except in compliance with the License. You may obtain a copy of the License at: 643 | * http://www.apache.org/licenses/LICENSE-2.0 644 | * 645 | * Unless required by applicable law or agreed to in writing, software distributed under 646 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 647 | * ANY KIND, either express or implied. See the License for the specific language 648 | * governing permissions and limitations under the License. 649 | * 650 | * @author Brian Reavis 651 | */ 652 | 653 | /*jshint curly:false */ 654 | /*jshint browser:true */ 655 | 656 | (function(root, factory) { 657 | if (typeof define === 'function' && define.amd) { 658 | define('selectize', ['jquery','sifter','microplugin'], factory); 659 | } else if (typeof exports === 'object') { 660 | module.exports = factory(require('jquery'), require('sifter'), require('microplugin')); 661 | } else { 662 | root.Selectize = factory(root.jQuery, root.Sifter, root.MicroPlugin); 663 | } 664 | }(this, function($, Sifter, MicroPlugin) { 665 | 'use strict'; 666 | 667 | var highlight = function($element, pattern) { 668 | if (typeof pattern === 'string' && !pattern.length) return; 669 | var regex = (typeof pattern === 'string') ? new RegExp(pattern, 'i') : pattern; 670 | 671 | var highlight = function(node) { 672 | var skip = 0; 673 | // Wrap matching part of text node with highlighting , e.g. 674 | // Soccer -> Soccer for regex = /soc/i 675 | if (node.nodeType === 3) { 676 | var pos = node.data.search(regex); 677 | if (pos >= 0 && node.data.length > 0) { 678 | var match = node.data.match(regex); 679 | var spannode = document.createElement('span'); 680 | spannode.className = 'highlight'; 681 | var middlebit = node.splitText(pos); 682 | var endbit = middlebit.splitText(match[0].length); 683 | var middleclone = middlebit.cloneNode(true); 684 | spannode.appendChild(middleclone); 685 | middlebit.parentNode.replaceChild(spannode, middlebit); 686 | skip = 1; 687 | } 688 | } 689 | // Recurse element node, looking for child text nodes to highlight, unless element 690 | // is childless, 48 | ``` 49 | 50 | Selectize Theme styles will be added to `