Add bootstrap-tagsinput library

This commit is contained in:
Stefan Parviainen 2014-12-21 12:44:57 +01:00
parent aa73259a47
commit b8081624c5
5 changed files with 1589 additions and 0 deletions

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 Tim Schlechter
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1 @@
Taken from https://github.com/gdibble/bootstrap-tagsinput/tree/traditionalPlaceholderEffect which has proper support for placeholders

View file

@ -0,0 +1,879 @@
<!DOCTYPE html>
<html lang="en" class="">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Language" content="en">
<title>bootstrap-tagsinput/README.md at master · TimSchlechter/bootstrap-tagsinput · GitHub</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-114.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-144.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144.png">
<meta property="fb:app_id" content="1401488693436528">
<meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="TimSchlechter/bootstrap-tagsinput" name="twitter:title" /><meta content="bootstrap-tagsinput - jQuery tags input plugin based on Twitter Bootstrap." name="twitter:description" /><meta content="https://avatars1.githubusercontent.com/u/2721613?v=3&amp;s=400" name="twitter:image:src" />
<meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="https://avatars1.githubusercontent.com/u/2721613?v=3&amp;s=400" property="og:image" /><meta content="TimSchlechter/bootstrap-tagsinput" property="og:title" /><meta content="https://github.com/TimSchlechter/bootstrap-tagsinput" property="og:url" /><meta content="bootstrap-tagsinput - jQuery tags input plugin based on Twitter Bootstrap." property="og:description" />
<meta name="browser-stats-url" content="/_stats">
<link rel="assets" href="https://assets-cdn.github.com/">
<link rel="conduit-xhr" href="https://ghconduit.com:25035">
<meta name="pjax-timeout" content="1000">
<meta name="msapplication-TileImage" content="/windows-tile.png">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="selected-link" value="repo_source" data-pjax-transient>
<meta name="google-analytics" content="UA-3769691-2">
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="collector-cdn.github.com" name="octolytics-script-host" /><meta content="github" name="octolytics-app-id" /><meta content="05C412F3:5EFA:620CC:54968B9C" name="octolytics-dimension-request_id" />
<meta content="Rails, view, blob#show" name="analytics-event" />
<link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">
<meta content="authenticity_token" name="csrf-param" />
<meta content="pq46YRAN8EIxwiqw1PBmOS18o8ukCrBKyIwYs6EhhTJPiGbEXhKdJxdkbRWl+VYne3E3iSUijxSIsYnZnQddlg==" name="csrf-token" />
<link href="https://assets-cdn.github.com/assets/github-9bcf5def7eb44e2a101b20aaecf3707f4b0a10ab8f4d6eebec29371f821c4b29.css" media="all" rel="stylesheet" type="text/css" />
<link href="https://assets-cdn.github.com/assets/github2-47bc67324d463c7cecb5ee4c009628c91db85b0e9288a9e663f2d06ff9e03088.css" media="all" rel="stylesheet" type="text/css" />
<meta http-equiv="x-pjax-version" content="cffc32e08a29062b908cc3ddb47285af">
<meta name="description" content="bootstrap-tagsinput - jQuery tags input plugin based on Twitter Bootstrap.">
<meta name="go-import" content="github.com/TimSchlechter/bootstrap-tagsinput git https://github.com/TimSchlechter/bootstrap-tagsinput.git">
<meta content="2721613" name="octolytics-dimension-user_id" /><meta content="TimSchlechter" name="octolytics-dimension-user_login" /><meta content="11534941" name="octolytics-dimension-repository_id" /><meta content="TimSchlechter/bootstrap-tagsinput" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="11534941" name="octolytics-dimension-repository_network_root_id" /><meta content="TimSchlechter/bootstrap-tagsinput" name="octolytics-dimension-repository_network_root_nwo" />
<link href="https://github.com/TimSchlechter/bootstrap-tagsinput/commits/master.atom" rel="alternate" title="Recent Commits to bootstrap-tagsinput:master" type="application/atom+xml">
</head>
<body class="logged_out env-production vis-public page-blob">
<a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a>
<div class="wrapper">
<div class="header header-logged-out" role="banner">
<div class="container clearfix">
<a class="header-logo-wordmark" href="https://github.com/" ga-data-click="(Logged out) Header, go to homepage, icon:logo-wordmark">
<span class="mega-octicon octicon-logo-github"></span>
</a>
<div class="header-actions" role="navigation">
<a class="button primary" href="/join" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a>
<a class="button" href="/login?return_to=%2FTimSchlechter%2Fbootstrap-tagsinput%2Fblob%2Fmaster%2FREADME.md" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a>
</div>
<div class="site-search repo-scope js-site-search" role="search">
<form accept-charset="UTF-8" action="/TimSchlechter/bootstrap-tagsinput/search" class="js-site-search-form" data-global-search-url="/search" data-repo-search-url="/TimSchlechter/bootstrap-tagsinput/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>
<input type="text"
class="js-site-search-field is-clearable"
data-hotkey="s"
name="q"
placeholder="Search"
data-global-scope-placeholder="Search GitHub"
data-repo-scope-placeholder="Search"
tabindex="1"
autocapitalize="off">
<div class="scope-badge">This repository</div>
</form>
</div>
<ul class="header-nav left" role="navigation">
<li class="header-nav-item">
<a class="header-nav-link" href="/explore" data-ga-click="(Logged out) Header, go to explore, text:explore">Explore</a>
</li>
<li class="header-nav-item">
<a class="header-nav-link" href="/features" data-ga-click="(Logged out) Header, go to features, text:features">Features</a>
</li>
<li class="header-nav-item">
<a class="header-nav-link" href="https://enterprise.github.com/" data-ga-click="(Logged out) Header, go to enterprise, text:enterprise">Enterprise</a>
</li>
<li class="header-nav-item">
<a class="header-nav-link" href="/blog" data-ga-click="(Logged out) Header, go to blog, text:blog">Blog</a>
</li>
</ul>
</div>
</div>
<div id="start-of-content" class="accessibility-aid"></div>
<div class="site" itemscope itemtype="http://schema.org/WebPage">
<div id="js-flash-container">
</div>
<div class="pagehead repohead instapaper_ignore readability-menu">
<div class="container">
<ul class="pagehead-actions">
<li>
<a href="/login?return_to=%2FTimSchlechter%2Fbootstrap-tagsinput"
class="minibutton with-count star-button tooltipped tooltipped-n"
aria-label="You must be signed in to star a repository" rel="nofollow">
<span class="octicon octicon-star"></span>
Star
</a>
<a class="social-count js-social-count" href="/TimSchlechter/bootstrap-tagsinput/stargazers">
755
</a>
</li>
<li>
<a href="/login?return_to=%2FTimSchlechter%2Fbootstrap-tagsinput"
class="minibutton with-count js-toggler-target fork-button tooltipped tooltipped-n"
aria-label="You must be signed in to fork a repository" rel="nofollow">
<span class="octicon octicon-repo-forked"></span>
Fork
</a>
<a href="/TimSchlechter/bootstrap-tagsinput/network" class="social-count">
307
</a>
</li>
</ul>
<h1 itemscope itemtype="http://data-vocabulary.org/Breadcrumb" class="entry-title public">
<span class="mega-octicon octicon-repo"></span>
<span class="author"><a href="/TimSchlechter" class="url fn" itemprop="url" rel="author"><span itemprop="title">TimSchlechter</span></a></span><!--
--><span class="path-divider">/</span><!--
--><strong><a href="/TimSchlechter/bootstrap-tagsinput" class="js-current-repository" data-pjax="#js-repo-pjax-container">bootstrap-tagsinput</a></strong>
<span class="page-context-loader">
<img alt="" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</span>
</h1>
</div><!-- /.container -->
</div><!-- /.repohead -->
<div class="container">
<div class="repository-with-sidebar repo-container new-discussion-timeline ">
<div class="repository-sidebar clearfix">
<nav class="sunken-menu repo-nav js-repo-nav js-sidenav-container-pjax js-octicon-loaders"
role="navigation"
data-pjax="#js-repo-pjax-container"
data-issue-count-url="/TimSchlechter/bootstrap-tagsinput/issues/counts">
<ul class="sunken-menu-group">
<li class="tooltipped tooltipped-w" aria-label="Code">
<a href="/TimSchlechter/bootstrap-tagsinput" aria-label="Code" class="selected js-selected-navigation-item sunken-menu-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /TimSchlechter/bootstrap-tagsinput">
<span class="octicon octicon-code"></span> <span class="full-word">Code</span>
<img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped tooltipped-w" aria-label="Issues">
<a href="/TimSchlechter/bootstrap-tagsinput/issues" aria-label="Issues" class="js-selected-navigation-item sunken-menu-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /TimSchlechter/bootstrap-tagsinput/issues">
<span class="octicon octicon-issue-opened"></span> <span class="full-word">Issues</span>
<span class="js-issue-replace-counter"></span>
<img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped tooltipped-w" aria-label="Pull Requests">
<a href="/TimSchlechter/bootstrap-tagsinput/pulls" aria-label="Pull Requests" class="js-selected-navigation-item sunken-menu-item" data-hotkey="g p" data-selected-links="repo_pulls /TimSchlechter/bootstrap-tagsinput/pulls">
<span class="octicon octicon-git-pull-request"></span> <span class="full-word">Pull Requests</span>
<span class="js-pull-replace-counter"></span>
<img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
<div class="sunken-menu-separator"></div>
<ul class="sunken-menu-group">
<li class="tooltipped tooltipped-w" aria-label="Pulse">
<a href="/TimSchlechter/bootstrap-tagsinput/pulse" aria-label="Pulse" class="js-selected-navigation-item sunken-menu-item" data-selected-links="pulse /TimSchlechter/bootstrap-tagsinput/pulse">
<span class="octicon octicon-pulse"></span> <span class="full-word">Pulse</span>
<img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped tooltipped-w" aria-label="Graphs">
<a href="/TimSchlechter/bootstrap-tagsinput/graphs" aria-label="Graphs" class="js-selected-navigation-item sunken-menu-item" data-selected-links="repo_graphs repo_contributors /TimSchlechter/bootstrap-tagsinput/graphs">
<span class="octicon octicon-graph"></span> <span class="full-word">Graphs</span>
<img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
</nav>
<div class="only-with-full-nav">
<div class="clone-url open"
data-protocol-type="http"
data-url="/users/set_protocol?protocol_selector=http&amp;protocol_type=clone">
<h3><span class="text-emphasized">HTTPS</span> clone URL</h3>
<div class="input-group js-zeroclipboard-container">
<input type="text" class="input-mini input-monospace js-url-field js-zeroclipboard-target"
value="https://github.com/TimSchlechter/bootstrap-tagsinput.git" readonly="readonly">
<span class="input-group-button">
<button aria-label="Copy to clipboard" class="js-zeroclipboard minibutton zeroclipboard-button" data-copied-hint="Copied!" type="button"><span class="octicon octicon-clippy"></span></button>
</span>
</div>
</div>
<div class="clone-url "
data-protocol-type="subversion"
data-url="/users/set_protocol?protocol_selector=subversion&amp;protocol_type=clone">
<h3><span class="text-emphasized">Subversion</span> checkout URL</h3>
<div class="input-group js-zeroclipboard-container">
<input type="text" class="input-mini input-monospace js-url-field js-zeroclipboard-target"
value="https://github.com/TimSchlechter/bootstrap-tagsinput" readonly="readonly">
<span class="input-group-button">
<button aria-label="Copy to clipboard" class="js-zeroclipboard minibutton zeroclipboard-button" data-copied-hint="Copied!" type="button"><span class="octicon octicon-clippy"></span></button>
</span>
</div>
</div>
<p class="clone-options">You can clone with
<a href="#" class="js-clone-selector" data-protocol="http">HTTPS</a> or <a href="#" class="js-clone-selector" data-protocol="subversion">Subversion</a>.
<a href="https://help.github.com/articles/which-remote-url-should-i-use" class="help tooltipped tooltipped-n" aria-label="Get help on which URL is right for you.">
<span class="octicon octicon-question"></span>
</a>
</p>
<a href="/TimSchlechter/bootstrap-tagsinput/archive/master.zip"
class="minibutton sidebar-button"
aria-label="Download the contents of TimSchlechter/bootstrap-tagsinput as a zip file"
title="Download the contents of TimSchlechter/bootstrap-tagsinput as a zip file"
rel="nofollow">
<span class="octicon octicon-cloud-download"></span>
Download ZIP
</a>
</div>
</div><!-- /.repository-sidebar -->
<div id="js-repo-pjax-container" class="repository-content context-loader-container" data-pjax-container>
<a href="/TimSchlechter/bootstrap-tagsinput/blob/a4657365808a224fe8aa950c14b96ecfce58b290/README.md" class="hidden js-permalink-shortcut" data-hotkey="y">Permalink</a>
<!-- blob contrib key: blob_contributors:v21:002463f2fb860593a8410f2c5c54cd3a -->
<div class="file-navigation js-zeroclipboard-container">
<div class="select-menu js-menu-container js-select-menu left">
<span class="minibutton select-menu-button js-menu-target css-truncate" data-hotkey="w"
data-master-branch="master"
data-ref="master"
title="master"
role="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true">
<span class="octicon octicon-git-branch"></span>
<i>branch:</i>
<span class="js-select-button css-truncate-target">master</span>
</span>
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true">
<div class="select-menu-modal">
<div class="select-menu-header">
<span class="select-menu-title">Switch branches/tags</span>
<span class="octicon octicon-x js-menu-close" role="button" aria-label="Close"></span>
</div> <!-- /.select-menu-header -->
<div class="select-menu-filters">
<div class="select-menu-text-filter">
<input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
</div>
<div class="select-menu-tabs">
<ul>
<li class="select-menu-tab">
<a href="#" data-tab-filter="branches" class="js-select-menu-tab">Branches</a>
</li>
<li class="select-menu-tab">
<a href="#" data-tab-filter="tags" class="js-select-menu-tab">Tags</a>
</li>
</ul>
</div><!-- /.select-menu-tabs -->
</div><!-- /.select-menu-filters -->
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/blob/gh-pages/README.md"
data-name="gh-pages"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="gh-pages">gh-pages</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item selected">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/blob/master/README.md"
data-name="master"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="master">master</a>
</div> <!-- /.select-menu-item -->
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div> <!-- /.select-menu-list -->
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.4.2/README.md"
data-name="0.4.2"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.4.2">0.4.2</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.4.1/README.md"
data-name="0.4.1"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.4.1">0.4.1</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.4/README.md"
data-name="0.4"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.4">0.4</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.14/README.md"
data-name="0.3.14"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.14">0.3.14</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.13/README.md"
data-name="0.3.13"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.13">0.3.13</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.12/README.md"
data-name="0.3.12"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.12">0.3.12</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.11/README.md"
data-name="0.3.11"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.11">0.3.11</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.10/README.md"
data-name="0.3.10"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.10">0.3.10</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.9/README.md"
data-name="0.3.9"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.9">0.3.9</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.8/README.md"
data-name="0.3.8"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.8">0.3.8</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.7/README.md"
data-name="0.3.7"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.7">0.3.7</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.6/README.md"
data-name="0.3.6"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.6">0.3.6</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.5/README.md"
data-name="0.3.5"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.5">0.3.5</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.4/README.md"
data-name="0.3.4"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.4">0.3.4</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.3/README.md"
data-name="0.3.3"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.3">0.3.3</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.2/README.md"
data-name="0.3.2"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.2">0.3.2</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.1/README.md"
data-name="0.3.1"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.1">0.3.1</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.3.0/README.md"
data-name="0.3.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.3.0">0.3.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.2.3/README.md"
data-name="0.2.3"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.2.3">0.2.3</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.2.2/README.md"
data-name="0.2.2"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.2.2">0.2.2</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.2.1/README.md"
data-name="0.2.1"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.2.1">0.2.1</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.2.0/README.md"
data-name="0.2.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.2.0">0.2.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.1.1/README.md"
data-name="0.1.1"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.1.1">0.1.1</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/TimSchlechter/bootstrap-tagsinput/tree/0.1.0/README.md"
data-name="0.1.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text css-truncate-target"
title="0.1.0">0.1.0</a>
</div> <!-- /.select-menu-item -->
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div> <!-- /.select-menu-list -->
</div> <!-- /.select-menu-modal -->
</div> <!-- /.select-menu-modal-holder -->
</div> <!-- /.select-menu -->
<div class="button-group right">
<a href="/TimSchlechter/bootstrap-tagsinput/find/master"
class="js-show-file-finder minibutton empty-icon tooltipped tooltipped-s"
data-pjax
data-hotkey="t"
aria-label="Quickly jump between files">
<span class="octicon octicon-list-unordered"></span>
</a>
<button aria-label="Copy file path to clipboard" class="js-zeroclipboard minibutton zeroclipboard-button" data-copied-hint="Copied!" type="button"><span class="octicon octicon-clippy"></span></button>
</div>
<div class="breadcrumb js-zeroclipboard-target">
<span class='repo-root js-repo-root'><span itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/TimSchlechter/bootstrap-tagsinput" class="" data-branch="master" data-direction="back" data-pjax="true" itemscope="url"><span itemprop="title">bootstrap-tagsinput</span></a></span></span><span class="separator">/</span><strong class="final-path">README.md</strong>
</div>
</div>
<div class="commit file-history-tease">
<div class="file-history-tease-header">
<img alt="Tim Schlechter" class="avatar" data-user="2721613" height="24" src="https://avatars3.githubusercontent.com/u/2721613?v=3&amp;s=48" width="24" />
<span class="author"><a href="/TimSchlechter" rel="author">TimSchlechter</a></span>
<time datetime="2014-07-30T18:40:53Z" is="relative-time">Jul 30, 2014</time>
<div class="commit-title">
<a href="/TimSchlechter/bootstrap-tagsinput/commit/a64536d346d252a6fb5d013a53ff0b6a6a991ba8" class="message" data-pjax="true" title="Release build 0.4">Release build 0.4</a>
</div>
</div>
<div class="participation">
<p class="quickstat">
<a href="#blob_contributors_box" rel="facebox">
<strong>1</strong>
contributor
</a>
</p>
</div>
<div id="blob_contributors_box" style="display:none">
<h2 class="facebox-header">Users who have contributed to this file</h2>
<ul class="facebox-user-list">
<li class="facebox-user-list-item">
<img alt="Tim Schlechter" data-user="2721613" height="24" src="https://avatars3.githubusercontent.com/u/2721613?v=3&amp;s=48" width="24" />
<a href="/TimSchlechter">TimSchlechter</a>
</li>
</ul>
</div>
</div>
<div class="file-box">
<div class="file">
<div class="meta clearfix">
<div class="info file-name">
<span>70 lines (61 sloc)</span>
<span class="meta-divider"></span>
<span>3.157 kb</span>
</div>
<div class="actions">
<div class="button-group">
<a href="/TimSchlechter/bootstrap-tagsinput/raw/master/README.md" class="minibutton " id="raw-url">Raw</a>
<a href="/TimSchlechter/bootstrap-tagsinput/blame/master/README.md" class="minibutton js-update-url-with-hash">Blame</a>
<a href="/TimSchlechter/bootstrap-tagsinput/commits/master/README.md" class="minibutton " rel="nofollow">History</a>
</div><!-- /.button-group -->
<a class="octicon-button disabled tooltipped tooltipped-w" href="#"
aria-label="You must be signed in to make or propose changes"><span class="octicon octicon-pencil"></span></a>
<a class="octicon-button danger disabled tooltipped tooltipped-w" href="#"
aria-label="You must be signed in to make or propose changes">
<span class="octicon octicon-trashcan"></span>
</a>
</div><!-- /.actions -->
</div>
<div id="readme" class="blob instapaper_body">
<article class="markdown-body entry-content" itemprop="mainContentOfPage"><h1>
<a id="user-content-bootstrap-tags-input-" class="anchor" href="#bootstrap-tags-input-" aria-hidden="true"><span class="octicon octicon-link"></span></a>Bootstrap Tags Input <a href="https://travis-ci.org/TimSchlechter/bootstrap-tagsinput"><img src="https://camo.githubusercontent.com/2d02546931244241329b98071825212a0d77dd4e/68747470733a2f2f7472617669732d63692e6f72672f54696d5363686c6563687465722f626f6f7473747261702d74616773696e7075742e7376673f6272616e63683d6d6173746572" alt="Build Status" data-canonical-src="https://travis-ci.org/TimSchlechter/bootstrap-tagsinput.svg?branch=master" style="max-width:100%;"></a>
</h1>
<p>Bootstrap Tags Input is a jQuery plugin providing a Twitter Bootstrap user interface for managing tags.</p>
<h2>
<a id="user-content-usage" class="anchor" href="#usage" aria-hidden="true"><span class="octicon octicon-link"></span></a>Usage</h2>
<p>Examples can be found <a href="http://timschlechter.github.com/bootstrap-tagsinput/examples/">here</a>.</p>
<h2>
<a id="user-content-features" class="anchor" href="#features" aria-hidden="true"><span class="octicon octicon-link"></span></a>Features</h2>
<ul class="task-list">
<li>Objects as tags</li>
<li>True multi value</li>
<li>Typeahead</li>
<li>Designed for Bootstrap 2.3.2 and 3</li>
</ul>
<h3>
<a id="user-content-objects-as-tags" class="anchor" href="#objects-as-tags" aria-hidden="true"><span class="octicon octicon-link"></span></a>Objects as tags</h3>
<p>Not just support for using strings! This means you can use different values
for a tag's label and value. Each tag also holds a reference to the object
by which it was created, so by calling <code>tagsinput('items')</code> an
array of the original items is returned.</p>
<h3>
<a id="user-content-true-multi-value-support" class="anchor" href="#true-multi-value-support" aria-hidden="true"><span class="octicon octicon-link"></span></a>True multi value support</h3>
<p>Other implementations just concatenate the values to a comma separated string.
This results in <code>val()</code> returning just this string, and when
submitting the form, only one big, concatenated value is sent in the request.</p>
<p>Bootstrap Tags Input provides true multivalue support. Just use a
<code>&lt;select multiple /&gt;</code> as your input element, and
<code>val()</code> will return an array of the tag values. When submitting the
form, an array of values will be sent with the request.</p>
<h3>
<a id="user-content-typeahead-support" class="anchor" href="#typeahead-support" aria-hidden="true"><span class="octicon octicon-link"></span></a>Typeahead support</h3>
<p>Integrates with Twitter Bootstraps' 2.3.2 typeahead, or use custom typeahead when using Bootstrap 3.</p>
<h2>
<a id="user-content-development" class="anchor" href="#development" aria-hidden="true"><span class="octicon octicon-link"></span></a>Development</h2>
<p>Install dependencies:</p>
<pre>
npm install
bower install
</pre>
<p>Test:</p>
<pre>
grunt test
</pre>
<p>Build:</p>
<pre>
grunt build
</pre>
<h2>
<a id="user-content-history" class="anchor" href="#history" aria-hidden="true"><span class="octicon octicon-link"></span></a>History</h2>
<ul class="task-list">
<li>0.4
<ul class="task-list">
<li><a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/73">Fix typeahead when using Bootstrap 3</a></li>
</ul>
</li>
<li>0.3.13
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/issues/5">#5: Trigger events on original input/select</a>
</li>
<li> Loads of fixes merged with help of @janvt, @rlidwka and @kuraga: thanks for helping me out!</li>
</ul>
</li>
<li>0.3.9
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/issues/48">#48: Type ahead stops when entering second character</a>
</li>
</ul>
</li>
<li>0.3.8
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/43">#43: Add support for placeholder</a>
</li>
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/46">#46: ie 8 compatibility, replace indexOf method</a>
</li>
</ul>
</li>
<li>0.3.7
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/issues/39">#39: flash when duplicate is entered</a>
</li>
</ul>
</li>
<li>0.3.6
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/issues/34">#34: Error in ReloadPage</a>
</li>
</ul>
</li>
<li>0.3.5
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/issues/10">#10: confirmKeys option</a>
</li>
</ul>
</li>
<li>0.3.4
<ul class="task-list">
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/24">#24: Add bsTagsInput angular directive &amp; example for bootstrap3 with typeahea...</a>
</li>
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/28">#28: Limit number of tags, enable/disable input</a>
</li>
<li> <a href="https://github.com/TimSchlechter/bootstrap-tagsinput/pull/33">#33: Avoid conflict with other selects when checking for value presence</a>
</li>
</ul>
</li>
</ul>
<h2>
<a id="user-content-license" class="anchor" href="#license" aria-hidden="true"><span class="octicon octicon-link"></span></a>License</h2>
<p>This project is licensed under <a href="https://raw.github.com/TimSchlechter/bootstrap-tagsinput/master/LICENSE" title="Read more about the MIT license">MIT</a>.</p>
</article>
</div>
</div>
</div>
<a href="#jump-to-line" rel="facebox[.linejump]" data-hotkey="l" style="display:none">Jump to Line</a>
<div id="jump-to-line" style="display:none">
<form accept-charset="UTF-8" class="js-jump-to-line-form">
<input class="linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" autofocus>
<button type="submit" class="button">Go</button>
</form>
</div>
</div>
</div><!-- /.repo-container -->
<div class="modal-backdrop"></div>
</div><!-- /.container -->
</div><!-- /.site -->
</div><!-- /.wrapper -->
<div class="container">
<div class="site-footer" role="contentinfo">
<ul class="site-footer-links right">
<li><a href="https://status.github.com/">Status</a></li>
<li><a href="https://developer.github.com">API</a></li>
<li><a href="http://training.github.com">Training</a></li>
<li><a href="http://shop.github.com">Shop</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/about">About</a></li>
</ul>
<a href="/" aria-label="Homepage">
<span class="mega-octicon octicon-mark-github" title="GitHub"></span>
</a>
<ul class="site-footer-links">
<li>&copy; 2014 <span title="0.02664s from github-fe122-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
<li><a href="/site/terms">Terms</a></li>
<li><a href="/site/privacy">Privacy</a></li>
<li><a href="/security">Security</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div><!-- /.site-footer -->
</div><!-- /.container -->
<div class="fullscreen-overlay js-fullscreen-overlay" id="fullscreen_overlay">
<div class="fullscreen-container js-suggester-container">
<div class="textarea-wrap">
<textarea name="fullscreen-contents" id="fullscreen-contents" class="fullscreen-contents js-fullscreen-contents" placeholder=""></textarea>
<div class="suggester-container">
<div class="suggester fullscreen-suggester js-suggester js-navigation-container"></div>
</div>
</div>
</div>
<div class="fullscreen-sidebar">
<a href="#" class="exit-fullscreen js-exit-fullscreen tooltipped tooltipped-w" aria-label="Exit Zen Mode">
<span class="mega-octicon octicon-screen-normal"></span>
</a>
<a href="#" class="theme-switcher js-theme-switcher tooltipped tooltipped-w"
aria-label="Switch themes">
<span class="octicon octicon-color-mode"></span>
</a>
</div>
</div>
<div id="ajax-error-message" class="flash flash-error">
<span class="octicon octicon-alert"></span>
<a href="#" class="octicon octicon-x flash-close js-ajax-error-dismiss" aria-label="Dismiss error"></a>
Something went wrong with that request. Please try again.
</div>
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-fc447938e306b7b2c26a33cfee9dfda9052aeb1aa6ad84b72f1b35fd008efe9e.js" type="text/javascript"></script>
<script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-56c56f7fe2ed90ca50b9eefebccd56f3b9729a85d7ba17f0f9c9ebd02f20a7e3.js" type="text/javascript"></script>
</body>
</html>

View file

@ -0,0 +1,46 @@
.bootstrap-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
display: inline-block;
padding: 4px 6px;
margin-bottom: 10px;
color: #555;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
cursor: text;
}
.bootstrap-tagsinput input {
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0;
margin: 0;
width: auto !important;
max-width: inherit;
}
.bootstrap-tagsinput input:focus {
border: none;
box-shadow: none;
}
.bootstrap-tagsinput .tag {
margin-right: 2px;
color: white;
}
.bootstrap-tagsinput .tag [data-role="remove"] {
margin-left: 8px;
cursor: pointer;
}
.bootstrap-tagsinput .tag [data-role="remove"]:after {
content: "x";
padding: 0px 2px;
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover:active {
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}

View file

@ -0,0 +1,643 @@
(function ($) {
"use strict";
var defaultOptions = {
tagClass: function(item) {
return 'label label-info';
},
itemValue: function(item) {
return item ? item.toString() : item;
},
itemText: function(item) {
return this.itemValue(item);
},
freeInput: true,
addOnBlur: true,
maxTags: undefined,
maxChars: undefined,
confirmKeys: [13, 44],
onTagExists: function(item, $tag) {
$tag.hide().fadeIn();
},
trimValue: false,
allowDuplicates: false
};
/**
* Constructor function
*/
function TagsInput(element, options) {
this.itemsArray = [];
this.$element = $(element);
this.$element.hide();
this.isSelect = (element.tagName === 'SELECT');
this.multiple = (this.isSelect && element.hasAttribute('multiple'));
this.objectItems = options && options.itemValue;
this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
this.inputSize = Math.max(1, this.placeholderText.length);
this.$container = $('<div class="bootstrap-tagsinput"></div>');
this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
this.$element.after(this.$container);
var inputWidth = (this.inputSize < 3 ? 3 : this.inputSize) + "em";
this.$input.get(0).style.cssText = "width: " + inputWidth + " !important;";
this.build(options);
}
TagsInput.prototype = {
constructor: TagsInput,
/**
* Adds the given item as a new tag. Pass true to dontPushVal to prevent
* updating the elements val()
*/
add: function(item, dontPushVal) {
var self = this;
if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
return;
// Ignore falsey values, except false
if (item !== false && !item)
return;
// Trim value
if (typeof item === "string" && self.options.trimValue) {
item = $.trim(item);
}
// Throw an error when trying to add an object while the itemValue option was not set
if (typeof item === "object" && !self.objectItems)
throw("Can't add objects when itemValue option is not set");
// Ignore strings only containg whitespace
if (item.toString().match(/^\s*$/))
return;
// If SELECT but not multiple, remove current tag
if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
self.remove(self.itemsArray[0]);
if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
var items = item.split(',');
if (items.length > 1) {
for (var i = 0; i < items.length; i++) {
this.add(items[i], true);
}
if (!dontPushVal)
self.pushVal();
return;
}
}
// raise beforeItemAdd arg
var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false });
self.$element.trigger(beforeItemAddEvent);
if (beforeItemAddEvent.cancel)
return;
item = beforeItemAddEvent.item
var itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item);
// Ignore items allready added
var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
if (existing && !self.options.allowDuplicates) {
// Invoke onTagExists
if (self.options.onTagExists) {
var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
self.options.onTagExists(item, $existingTag);
}
return;
}
// if length greater than limit
if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
return;
// register item in internal array and map
self.itemsArray.push(item);
//remove placeholder if there is an item, restore if no item(s)
if (self.itemsArray.length)
self.$input.attr('placeholder', '');
else
self.$input.attr('placeholder', self.placeholderText);
// add a tag element
var $tag = $('<span class="tag ' + htmlEncode(tagClass) + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
$tag.data('item', item);
self.findInputWrapper().before($tag);
$tag.after(' ');
// add <option /> if item represents a value not present in one of the <select />'s options
if (self.isSelect && !$('option[value="' + encodeURIComponent(itemValue) + '"]',self.$element)[0]) {
var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
$option.data('item', item);
$option.attr('value', itemValue);
self.$element.append($option);
}
//remove placeholder if there is an item, restore if no item(s)
if (self.itemsArray.length)
self.$input.attr('placeholder', '');
else
self.$input.attr('placeholder', self.placeholderText);
if (!dontPushVal)
self.pushVal();
// Add class when reached maxTags
if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
self.$container.addClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemAdded', { item: item }));
},
/**
* Removes the given item. Pass true to dontPushVal to prevent updating the
* elements val()
*/
remove: function(item, dontPushVal) {
var self = this;
if (self.objectItems) {
if (typeof item === "object")
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } );
else
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } );
item = item[item.length-1];
}
if (item) {
var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false });
self.$element.trigger(beforeItemRemoveEvent);
if (beforeItemRemoveEvent.cancel)
return;
$('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
$('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
if($.inArray(item, self.itemsArray) !== -1)
self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
}
//remove placeholder if there is an item, restore if no item(s)
if (self.itemsArray.length)
self.$input.attr('placeholder', '');
else
self.$input.attr('placeholder', self.placeholderText);
if (!dontPushVal)
self.pushVal();
// Remove class when reached maxTags
if (self.options.maxTags > self.itemsArray.length)
self.$container.removeClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemRemoved', { item: item }));
},
/**
* Removes all items
*/
removeAll: function() {
var self = this;
$('.tag', self.$container).remove();
$('option', self.$element).remove();
while(self.itemsArray.length > 0)
self.itemsArray.pop();
//remove placeholder if there is an item, restore if no item(s)
if (self.itemsArray.length)
self.$input.attr('placeholder', '');
else
self.$input.attr('placeholder', self.placeholderText);
self.pushVal();
},
/**
* Refreshes the tags so they match the text/value of their corresponding
* item.
*/
refresh: function() {
var self = this;
$('.tag', self.$container).each(function() {
var $tag = $(this),
item = $tag.data('item'),
itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item);
// Update tag's class and inner text
$tag.attr('class', null);
$tag.addClass('tag ' + htmlEncode(tagClass));
$tag.contents().filter(function() {
return this.nodeType == 3;
})[0].nodeValue = htmlEncode(itemText);
if (self.isSelect) {
var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
option.attr('value', itemValue);
}
});
},
/**
* Returns the items added as tags
*/
items: function() {
return this.itemsArray;
},
/**
* Assembly value by retrieving the value of each item, and set it on the
* element.
*/
pushVal: function() {
var self = this,
val = $.map(self.items(), function(item) {
return self.options.itemValue(item).toString();
});
self.$element.val(val, true).trigger('change');
},
/**
* Initializes the tags input behaviour on the element
*/
build: function(options) {
var self = this;
self.options = $.extend({}, defaultOptions, options);
// When itemValue is set, freeInput should always be false
if (self.objectItems)
self.options.freeInput = false;
makeOptionItemFunction(self.options, 'itemValue');
makeOptionItemFunction(self.options, 'itemText');
makeOptionFunction(self.options, 'tagClass');
// Typeahead Bootstrap version 2.3.2
if (self.options.typeahead) {
var typeahead = self.options.typeahead || {};
makeOptionFunction(typeahead, 'source');
self.$input.typeahead($.extend({}, typeahead, {
source: function (query, process) {
function processItems(items) {
var texts = [];
for (var i = 0; i < items.length; i++) {
var text = self.options.itemText(items[i]);
map[text] = items[i];
texts.push(text);
}
process(texts);
}
this.map = {};
var map = this.map,
data = typeahead.source(query);
if ($.isFunction(data.success)) {
// support for Angular callbacks
data.success(processItems);
} else if ($.isFunction(data.then)) {
// support for Angular promises
data.then(processItems);
} else {
// support for functions and jquery promises
$.when(data)
.then(processItems);
}
},
updater: function (text) {
self.add(this.map[text]);
},
matcher: function (text) {
return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
},
sorter: function (texts) {
return texts.sort();
},
highlighter: function (text) {
var regex = new RegExp( '(' + this.query + ')', 'gi' );
return text.replace( regex, "<strong>$1</strong>" );
}
}));
}
// typeahead.js
if (self.options.typeaheadjs) {
var typeaheadjs = self.options.typeaheadjs || {};
self.$input.typeahead(null, typeaheadjs).on('typeahead:selected', $.proxy(function (obj, datum) {
if (typeaheadjs.valueKey)
self.add(datum[typeaheadjs.valueKey]);
else
self.add(datum);
self.$input.typeahead('val', '');
}, self));
}
self.$container.on('click', $.proxy(function(event) {
if (! self.$element.attr('disabled')) {
self.$input.removeAttr('disabled');
}
self.$input.focus();
}, self));
if (self.options.addOnBlur && self.options.freeInput) {
self.$input.on('focusout', $.proxy(function(event) {
// HACK: only process on focusout when no typeahead opened, to
// avoid adding the typeahead text as tag
if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
self.add(self.$input.val());
self.$input.val('');
}
}, self));
}
self.$container.on('keydown', 'input', $.proxy(function(event) {
var $input = $(event.target),
$inputWrapper = self.findInputWrapper();
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
switch (event.which) {
// BACKSPACE
case 8:
if (doGetCaretPosition($input[0]) === 0) {
var prev = $inputWrapper.prev();
if (prev) {
self.remove(prev.data('item'));
}
}
break;
// DELETE
case 46:
if (doGetCaretPosition($input[0]) === 0) {
var next = $inputWrapper.next();
if (next) {
self.remove(next.data('item'));
}
}
break;
// LEFT ARROW
case 37:
// Try to move the input before the previous tag
var $prevTag = $inputWrapper.prev();
if ($input.val().length === 0 && $prevTag[0]) {
$prevTag.before($inputWrapper);
$input.focus();
}
break;
// RIGHT ARROW
case 39:
// Try to move the input after the next tag
var $nextTag = $inputWrapper.next();
if ($input.val().length === 0 && $nextTag[0]) {
$nextTag.after($inputWrapper);
$input.focus();
}
break;
default:
// ignore
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
self.$container.on('keypress', 'input', $.proxy(function(event) {
var $input = $(event.target);
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
var text = $input.val(),
maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
$input.val('');
event.preventDefault();
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
// Remove icon clicked
self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
if (self.$element.attr('disabled')) {
return;
}
self.remove($(event.target).closest('.tag').data('item'));
}, self));
// Only add existing value as tags when using strings as tags
if (self.options.itemValue === defaultOptions.itemValue) {
if (self.$element[0].tagName === 'INPUT') {
self.add(self.$element.val());
} else {
$('option', self.$element).each(function() {
self.add($(this).attr('value'), true);
});
}
}
},
/**
* Removes all tagsinput behaviour and unregsiter all event handlers
*/
destroy: function() {
var self = this;
// Unbind events
self.$container.off('keypress', 'input');
self.$container.off('click', '[role=remove]');
self.$container.remove();
self.$element.removeData('tagsinput');
self.$element.show();
},
/**
* Sets focus on the tagsinput
*/
focus: function() {
this.$input.focus();
},
/**
* Returns the internal input element
*/
input: function() {
return this.$input;
},
/**
* Returns the element which is wrapped around the internal input. This
* is normally the $container, but typeahead.js moves the $input element.
*/
findInputWrapper: function() {
var elt = this.$input[0],
container = this.$container[0];
while(elt && elt.parentNode !== container)
elt = elt.parentNode;
return $(elt);
}
};
/**
* Register JQuery plugin
*/
$.fn.tagsinput = function(arg1, arg2) {
var results = [];
this.each(function() {
var tagsinput = $(this).data('tagsinput');
// Initialize a new tags input
if (!tagsinput) {
tagsinput = new TagsInput(this, arg1);
$(this).data('tagsinput', tagsinput);
results.push(tagsinput);
if (this.tagName === 'SELECT') {
$('option', $(this)).attr('selected', 'selected');
}
// Init tags from $(this).val()
$(this).val($(this).val());
} else if (!arg1 && !arg2) {
// tagsinput already exists
// no function, trying to init
results.push(tagsinput);
} else if(tagsinput[arg1] !== undefined) {
// Invoke function on existing tags input
var retVal = tagsinput[arg1](arg2);
if (retVal !== undefined)
results.push(retVal);
}
});
if ( typeof arg1 == 'string') {
// Return the results from the invoked function calls
return results.length > 1 ? results : results[0];
} else {
return results;
}
};
$.fn.tagsinput.Constructor = TagsInput;
/**
* Most options support both a string or number as well as a function as
* option value. This function makes sure that the option with the given
* key in the given options is wrapped in a function
*/
function makeOptionItemFunction(options, key) {
if (typeof options[key] !== 'function') {
var propertyName = options[key];
options[key] = function(item) { return item[propertyName]; };
}
}
function makeOptionFunction(options, key) {
if (typeof options[key] !== 'function') {
var value = options[key];
options[key] = function() { return value; };
}
}
/**
* HtmlEncodes the given value
*/
var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}
/**
* Returns the position of the caret in the given input field
* http://flightschool.acylt.com/devnotes/caret-position-woes/
*/
function doGetCaretPosition(oField) {
var iCaretPos = 0;
if (document.selection) {
oField.focus ();
var oSel = document.selection.createRange();
oSel.moveStart ('character', -oField.value.length);
iCaretPos = oSel.text.length;
} else if (oField.selectionStart || oField.selectionStart == '0') {
iCaretPos = oField.selectionStart;
}
return (iCaretPos);
}
/**
* Returns boolean indicates whether user has pressed an expected key combination.
* @param object keyPressEvent: JavaScript event object, refer
* http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
* @param object lookupList: expected key combinations, as in:
* [13, {which: 188, shiftKey: true}]
*/
function keyCombinationInList(keyPressEvent, lookupList) {
var found = false;
$.each(lookupList, function (index, keyCombination) {
if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
found = true;
return false;
}
if (keyPressEvent.which === keyCombination.which) {
var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
if (alt && shift && ctrl) {
found = true;
return false;
}
}
});
return found;
}
/**
* Initialize tagsinput behaviour on inputs and selects which have
* data-role=tagsinput
*/
$(function() {
$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
});
})(window.jQuery);