bootstrap-combobox 1.2
Sign up to get free protection for your applications and to get access to all the features.
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Bootstrap Combobox
|
2
|
+
|
3
|
+
We had need of a combobox at work and after looking around at the available options I was not happy with any of them. The project had all it's styling based on Twitter's Bootstrap, so building on that made sense.
|
4
|
+
|
5
|
+
## How to use it
|
6
|
+
|
7
|
+
The dependencies are the Bootstrap stylesheet(CSS or LESS) and also the typeahead javascript plugin. Include them and then the stylesheet(CSS or LESS) and javascript.
|
8
|
+
|
9
|
+
Then just activate the plugin on a normal select box(suggest having a blank option first):
|
10
|
+
|
11
|
+
<select class="combobox">
|
12
|
+
<option></option>
|
13
|
+
<option value="PA">Pennsylvania</option>
|
14
|
+
<option value="CT">Connecticut</option>
|
15
|
+
<option value="NY">New York</option>
|
16
|
+
<option value="MD">Maryland</option>
|
17
|
+
<option value="VA">Virginia</option>
|
18
|
+
</select>
|
19
|
+
|
20
|
+
<script type="text/javascript">
|
21
|
+
$(document).ready(function(){
|
22
|
+
$('.combobox').combobox();
|
23
|
+
});
|
24
|
+
</script>
|
25
|
+
|
26
|
+
## Live Example
|
27
|
+
|
28
|
+
http://dl.dropbox.com/u/21368/bootstrap-combobox/index.html
|
29
|
+
|
30
|
+
## Ruby
|
31
|
+
|
32
|
+
This is published/publishable as a ruby gem as well.
|
@@ -0,0 +1,240 @@
|
|
1
|
+
/* =============================================================
|
2
|
+
* bootstrap-combobox.js v1.1.3
|
3
|
+
* =============================================================
|
4
|
+
* Copyright 2012 Daniel Farrell
|
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
|
+
|
19
|
+
!function( $ ) {
|
20
|
+
|
21
|
+
"use strict";
|
22
|
+
|
23
|
+
var Combobox = function ( element, options ) {
|
24
|
+
this.options = $.extend({}, $.fn.combobox.defaults, options)
|
25
|
+
this.$source = $(element)
|
26
|
+
this.$container = this.setup()
|
27
|
+
this.$element = this.$container.find('input[type=text]')
|
28
|
+
this.$target = this.$container.find('input[type=hidden]')
|
29
|
+
this.$button = this.$container.find('.dropdown-toggle')
|
30
|
+
this.$menu = $(this.options.menu).appendTo('body')
|
31
|
+
this.matcher = this.options.matcher || this.matcher
|
32
|
+
this.sorter = this.options.sorter || this.sorter
|
33
|
+
this.highlighter = this.options.highlighter || this.highlighter
|
34
|
+
this.shown = false
|
35
|
+
this.selected = false
|
36
|
+
this.refresh()
|
37
|
+
this.transferAttributes()
|
38
|
+
this.listen()
|
39
|
+
}
|
40
|
+
|
41
|
+
/* NOTE: COMBOBOX EXTENDS BOOTSTRAP-TYPEAHEAD.js
|
42
|
+
========================================== */
|
43
|
+
|
44
|
+
Combobox.prototype = $.extend({}, $.fn.typeahead.Constructor.prototype, {
|
45
|
+
|
46
|
+
constructor: Combobox
|
47
|
+
|
48
|
+
, setup: function () {
|
49
|
+
var combobox = $(this.options.template)
|
50
|
+
this.$source.before(combobox)
|
51
|
+
this.$source.hide()
|
52
|
+
return combobox
|
53
|
+
}
|
54
|
+
|
55
|
+
, parse: function () {
|
56
|
+
var that = this
|
57
|
+
, map = {}
|
58
|
+
, source = []
|
59
|
+
, selected = false
|
60
|
+
this.$source.find('option').each(function() {
|
61
|
+
var option = $(this)
|
62
|
+
if (option.val() === '') {
|
63
|
+
that.options.placeholder = option.text()
|
64
|
+
return
|
65
|
+
}
|
66
|
+
map[option.text()] = option.val()
|
67
|
+
source.push(option.text())
|
68
|
+
if(option.attr('selected')) selected = option.text()
|
69
|
+
})
|
70
|
+
this.map = map
|
71
|
+
if (selected) {
|
72
|
+
this.$element.val(selected)
|
73
|
+
this.$container.addClass('combobox-selected')
|
74
|
+
this.selected = true
|
75
|
+
}
|
76
|
+
return source
|
77
|
+
}
|
78
|
+
|
79
|
+
, transferAttributes: function() {
|
80
|
+
this.options.placeholder = this.$source.attr('data-placeholder') || this.options.placeholder
|
81
|
+
this.$element.attr('placeholder', this.options.placeholder)
|
82
|
+
this.$target.prop('name', this.$source.prop('name'))
|
83
|
+
this.$target.val(this.$source.val())
|
84
|
+
this.$source.removeAttr('name') // Remove from source otherwise form will pass parameter twice.
|
85
|
+
this.$element.attr('required', this.$source.attr('required'))
|
86
|
+
this.$element.attr('rel', this.$source.attr('rel'))
|
87
|
+
this.$element.attr('title', this.$source.attr('title'))
|
88
|
+
this.$element.attr('class', this.$source.attr('class'))
|
89
|
+
this.$element.attr('tabindex', this.$source.attr('tabindex'))
|
90
|
+
this.$source.removeAttr('tabindex')
|
91
|
+
}
|
92
|
+
|
93
|
+
, toggle: function () {
|
94
|
+
if (this.$container.hasClass('combobox-selected')) {
|
95
|
+
this.clearTarget()
|
96
|
+
this.triggerChange()
|
97
|
+
this.clearElement()
|
98
|
+
} else {
|
99
|
+
if (this.shown) {
|
100
|
+
this.hide()
|
101
|
+
} else {
|
102
|
+
this.clearElement()
|
103
|
+
this.lookup()
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
, clearElement: function () {
|
109
|
+
this.$element.val('').focus()
|
110
|
+
}
|
111
|
+
|
112
|
+
, clearTarget: function () {
|
113
|
+
this.$source.val('')
|
114
|
+
this.$target.val('')
|
115
|
+
this.$container.removeClass('combobox-selected')
|
116
|
+
this.selected = false
|
117
|
+
}
|
118
|
+
|
119
|
+
, triggerChange: function () {
|
120
|
+
this.$source.trigger('change')
|
121
|
+
}
|
122
|
+
|
123
|
+
, refresh: function () {
|
124
|
+
this.source = this.parse()
|
125
|
+
this.options.items = this.source.length
|
126
|
+
}
|
127
|
+
|
128
|
+
// modified typeahead function adding container and target handling
|
129
|
+
, select: function () {
|
130
|
+
var val = this.$menu.find('.active').attr('data-value')
|
131
|
+
this.$element.val(this.updater(val)).trigger('change')
|
132
|
+
this.$source.val(this.map[val]).trigger('change')
|
133
|
+
this.$target.val(this.map[val]).trigger('change')
|
134
|
+
this.$container.addClass('combobox-selected')
|
135
|
+
this.selected = true
|
136
|
+
return this.hide()
|
137
|
+
}
|
138
|
+
|
139
|
+
// modified typeahead function removing the blank handling and source function handling
|
140
|
+
, lookup: function (event) {
|
141
|
+
this.query = this.$element.val()
|
142
|
+
return this.process(this.source)
|
143
|
+
}
|
144
|
+
|
145
|
+
// modified typeahead function adding button handling and remove mouseleave
|
146
|
+
, listen: function () {
|
147
|
+
this.$element
|
148
|
+
.on('focus', $.proxy(this.focus, this))
|
149
|
+
.on('blur', $.proxy(this.blur, this))
|
150
|
+
.on('keypress', $.proxy(this.keypress, this))
|
151
|
+
.on('keyup', $.proxy(this.keyup, this))
|
152
|
+
|
153
|
+
if (this.eventSupported('keydown')) {
|
154
|
+
this.$element.on('keydown', $.proxy(this.keydown, this))
|
155
|
+
}
|
156
|
+
|
157
|
+
this.$menu
|
158
|
+
.on('click', $.proxy(this.click, this))
|
159
|
+
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
|
160
|
+
.on('mouseleave', 'li', $.proxy(this.mouseleave, this))
|
161
|
+
|
162
|
+
this.$button
|
163
|
+
.on('click', $.proxy(this.toggle, this))
|
164
|
+
}
|
165
|
+
|
166
|
+
// modified typeahead function to clear on type and prevent on moving around
|
167
|
+
, keyup: function (e) {
|
168
|
+
switch(e.keyCode) {
|
169
|
+
case 40: // down arrow
|
170
|
+
case 39: // right arrow
|
171
|
+
case 38: // up arrow
|
172
|
+
case 37: // left arrow
|
173
|
+
case 36: // home
|
174
|
+
case 35: // end
|
175
|
+
case 16: // shift
|
176
|
+
case 17: // ctrl
|
177
|
+
case 18: // alt
|
178
|
+
break
|
179
|
+
|
180
|
+
case 9: // tab
|
181
|
+
case 13: // enter
|
182
|
+
if (!this.shown) return
|
183
|
+
this.select()
|
184
|
+
break
|
185
|
+
|
186
|
+
case 27: // escape
|
187
|
+
if (!this.shown) return
|
188
|
+
this.hide()
|
189
|
+
break
|
190
|
+
|
191
|
+
default:
|
192
|
+
this.clearTarget()
|
193
|
+
this.lookup()
|
194
|
+
}
|
195
|
+
|
196
|
+
e.stopPropagation()
|
197
|
+
e.preventDefault()
|
198
|
+
}
|
199
|
+
|
200
|
+
// modified typeahead function to force a match and add a delay on hide
|
201
|
+
, blur: function (e) {
|
202
|
+
var that = this
|
203
|
+
this.focused = false
|
204
|
+
var val = this.$element.val()
|
205
|
+
if (!this.selected && val !== '' ) {
|
206
|
+
this.$element.val('')
|
207
|
+
this.$source.val('').trigger('change')
|
208
|
+
this.$target.val('').trigger('change')
|
209
|
+
}
|
210
|
+
if (!this.mousedover && this.shown) setTimeout(function () { that.hide() }, 200)
|
211
|
+
}
|
212
|
+
|
213
|
+
// modified typeahead function to not hide
|
214
|
+
, mouseleave: function (e) {
|
215
|
+
this.mousedover = false
|
216
|
+
}
|
217
|
+
})
|
218
|
+
|
219
|
+
/* COMBOBOX PLUGIN DEFINITION
|
220
|
+
* =========================== */
|
221
|
+
|
222
|
+
$.fn.combobox = function ( option ) {
|
223
|
+
return this.each(function () {
|
224
|
+
var $this = $(this)
|
225
|
+
, data = $this.data('combobox')
|
226
|
+
, options = typeof option == 'object' && option
|
227
|
+
if(!data) $this.data('combobox', (data = new Combobox(this, options)))
|
228
|
+
if (typeof option == 'string') data[option]()
|
229
|
+
})
|
230
|
+
}
|
231
|
+
|
232
|
+
$.fn.combobox.defaults = {
|
233
|
+
template: '<div class="combobox-container"><input type="hidden" /><input type="text" autocomplete="off" /><span class="add-on btn dropdown-toggle" data-dropdown="dropdown"><span class="caret"/><span class="combobox-clear"><i class="icon-remove"/></span></span></div>'
|
234
|
+
, menu: '<ul class="typeahead typeahead-long dropdown-menu"></ul>'
|
235
|
+
, item: '<li><a href="#"></a></li>'
|
236
|
+
}
|
237
|
+
|
238
|
+
$.fn.combobox.Constructor = Combobox
|
239
|
+
|
240
|
+
}( window.jQuery );
|
@@ -0,0 +1,150 @@
|
|
1
|
+
.combobox-container {
|
2
|
+
margin-bottom: 5px;
|
3
|
+
*zoom: 1;
|
4
|
+
}
|
5
|
+
.combobox-container:before,
|
6
|
+
.combobox-container:after {
|
7
|
+
display: table;
|
8
|
+
content: "";
|
9
|
+
}
|
10
|
+
.combobox-container:after {
|
11
|
+
clear: both;
|
12
|
+
}
|
13
|
+
.combobox-container input,
|
14
|
+
.combobox-container .uneditable-input {
|
15
|
+
-webkit-border-radius: 0 3px 3px 0;
|
16
|
+
-moz-border-radius: 0 3px 3px 0;
|
17
|
+
border-radius: 0 3px 3px 0;
|
18
|
+
}
|
19
|
+
.combobox-container input:focus,
|
20
|
+
.combobox-container .uneditable-input:focus {
|
21
|
+
position: relative;
|
22
|
+
z-index: 2;
|
23
|
+
}
|
24
|
+
.combobox-container .uneditable-input {
|
25
|
+
border-left-color: #ccc;
|
26
|
+
}
|
27
|
+
.combobox-container .add-on {
|
28
|
+
float: left;
|
29
|
+
display: inline-block;
|
30
|
+
width: auto;
|
31
|
+
min-width: 16px;
|
32
|
+
height: inherit !important;
|
33
|
+
margin-right: -1px;
|
34
|
+
padding: 4px 5px;
|
35
|
+
font-weight: normal;
|
36
|
+
color: #999999;
|
37
|
+
text-align: center;
|
38
|
+
text-shadow: 0 1px 0 #ffffff;
|
39
|
+
background-color: #f5f5f5;
|
40
|
+
border: 1px solid #ccc;
|
41
|
+
-webkit-border-radius: 3px 0 0 3px;
|
42
|
+
-moz-border-radius: 3px 0 0 3px;
|
43
|
+
border-radius: 3px 0 0 3px;
|
44
|
+
|
45
|
+
}
|
46
|
+
.combobox-container .active {
|
47
|
+
background-color: #a9dba9;
|
48
|
+
border-color: #46a546;
|
49
|
+
}
|
50
|
+
.combobox-container input,
|
51
|
+
.combobox-container .uneditable-input {
|
52
|
+
float: left;
|
53
|
+
-webkit-border-radius: 3px 0 0 3px;
|
54
|
+
-moz-border-radius: 3px 0 0 3px;
|
55
|
+
border-radius: 3px 0 0 3px;
|
56
|
+
}
|
57
|
+
.combobox-container .uneditable-input {
|
58
|
+
border-left-color: #eee;
|
59
|
+
border-right-color: #ccc;
|
60
|
+
}
|
61
|
+
.combobox-container .add-on {
|
62
|
+
margin-right: 0;
|
63
|
+
margin-left: -1px;
|
64
|
+
-webkit-border-radius: 0 3px 3px 0;
|
65
|
+
-moz-border-radius: 0 3px 3px 0;
|
66
|
+
border-radius: 0 3px 3px 0;
|
67
|
+
}
|
68
|
+
.combobox-container input:first-child {
|
69
|
+
*margin-left: -160px;
|
70
|
+
}
|
71
|
+
.combobox-container input:first-child + .add-on {
|
72
|
+
*margin-left: -21px;
|
73
|
+
}
|
74
|
+
.combobox-container select {
|
75
|
+
display: inline-block;
|
76
|
+
width: 0;
|
77
|
+
height: 0;
|
78
|
+
border: 0;
|
79
|
+
padding: 0;
|
80
|
+
margin: 0;
|
81
|
+
text-indent: -99999px;
|
82
|
+
*text-indent: 0;
|
83
|
+
}
|
84
|
+
.form-search .combobox-container,
|
85
|
+
.form-inline .combobox-container {
|
86
|
+
display: inline-block;
|
87
|
+
margin-bottom: 0;
|
88
|
+
vertical-align: top;
|
89
|
+
}
|
90
|
+
.form-search .combobox-container .add-on,
|
91
|
+
.form-inline .combobox-container .add-on {
|
92
|
+
vertical-align: middle;
|
93
|
+
}
|
94
|
+
.combobox-selected .combobox-clear {
|
95
|
+
display: inline-block;
|
96
|
+
}
|
97
|
+
.combobox-selected .caret {
|
98
|
+
display: none;
|
99
|
+
}
|
100
|
+
.combobox-clear {
|
101
|
+
display: none;
|
102
|
+
width: 14px;
|
103
|
+
height: 14px;
|
104
|
+
line-height: 14px;
|
105
|
+
vertical-align: top;
|
106
|
+
opacity: 0.3;
|
107
|
+
filter: alpha(opacity=30);
|
108
|
+
}
|
109
|
+
.dropdown:hover .combobox-clear,
|
110
|
+
.open.dropdown .combobox-clear {
|
111
|
+
opacity: 1;
|
112
|
+
filter: alpha(opacity=100);
|
113
|
+
}
|
114
|
+
.btn .combobox-clear {
|
115
|
+
margin-top: 1px;
|
116
|
+
margin-left: 1px;
|
117
|
+
}
|
118
|
+
.btn:hover .combobox-clear,
|
119
|
+
.open.btn-group .combobox-clear {
|
120
|
+
opacity: 1;
|
121
|
+
filter: alpha(opacity=100);
|
122
|
+
}
|
123
|
+
.typeahead-long {
|
124
|
+
max-height: 300px;
|
125
|
+
overflow-y: auto;
|
126
|
+
}
|
127
|
+
.control-group.error .combobox-container .add-on {
|
128
|
+
color: #B94A48;
|
129
|
+
border-color: #B94A48;
|
130
|
+
}
|
131
|
+
.control-group.error .combobox-container .caret {
|
132
|
+
border-top-color: #B94A48;
|
133
|
+
}
|
134
|
+
.control-group.warning .combobox-container .add-on {
|
135
|
+
color: #C09853;
|
136
|
+
border-color: #C09853;
|
137
|
+
}
|
138
|
+
.control-group.warning .combobox-container .caret {
|
139
|
+
border-top-color: #C09853;
|
140
|
+
}
|
141
|
+
.control-group.success .combobox-container .add-on {
|
142
|
+
color: #468847;
|
143
|
+
border-color: #468847;
|
144
|
+
}
|
145
|
+
.control-group.success .combobox-container .caret {
|
146
|
+
border-top-color: #468847;
|
147
|
+
}
|
148
|
+
.btn .combobox-clear [class^="icon-"] {
|
149
|
+
line-height: 1.4em;
|
150
|
+
}
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bootstrap-combobox
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.2'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- danielfarrell
|
9
|
+
- denishaskin
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: railties
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '3.1'
|
31
|
+
description: Combobox for Bootstrap, based on Bootstrap typeahead
|
32
|
+
email:
|
33
|
+
- danielfarrell76@gmail.com
|
34
|
+
- denis@constantorbit.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- lib/bootstrap-combobox/version.rb
|
40
|
+
- lib/bootstrap-combobox.rb
|
41
|
+
- vendor/assets/javascripts/bootstrap-combobox.js
|
42
|
+
- vendor/assets/stylesheets/bootstrap-combobox.css
|
43
|
+
- README.md
|
44
|
+
homepage: https://github.com/danielfarrell/bootstrap-combobox
|
45
|
+
licenses:
|
46
|
+
- MIT
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.8.25
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: Combobox for Bootstrap, based on Bootstrap typeahead
|
69
|
+
test_files: []
|