less-rails-jasny-bootstrap 3.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +36 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +7 -0
- data/LICENSE +22 -0
- data/LICENSE.txt +21 -0
- data/README.md +81 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/jasny/bootstrap/fileinput.js +198 -0
- data/app/assets/javascripts/jasny/bootstrap/inputmask.js +360 -0
- data/app/assets/javascripts/jasny/bootstrap/offcanvas.js +318 -0
- data/app/assets/javascripts/jasny/bootstrap/rowlink.js +86 -0
- data/app/assets/javascripts/jasny/bootstrap/transition.js +50 -0
- data/app/assets/javascripts/jasny/jasny-bootstrap.js +5 -0
- data/app/assets/stylesheets/jasny/jasny-bootstrap.less +1 -0
- data/app/frameworks/jasny/bootstrap/alerts-fixed.less +39 -0
- data/app/frameworks/jasny/bootstrap/build/jasny-bootstrap.less +5 -0
- data/app/frameworks/jasny/bootstrap/build/mixins.less +61 -0
- data/app/frameworks/jasny/bootstrap/build/variables.less +216 -0
- data/app/frameworks/jasny/bootstrap/button-labels.less +38 -0
- data/app/frameworks/jasny/bootstrap/fileinput.less +122 -0
- data/app/frameworks/jasny/bootstrap/grid-container-smooth.less +10 -0
- data/app/frameworks/jasny/bootstrap/jasny-bootstrap.less +18 -0
- data/app/frameworks/jasny/bootstrap/nav-tab-alignment.less +97 -0
- data/app/frameworks/jasny/bootstrap/navmenu.less +273 -0
- data/app/frameworks/jasny/bootstrap/offcanvas.less +48 -0
- data/app/frameworks/jasny/bootstrap/rowlink.less +22 -0
- data/app/frameworks/jasny/bootstrap/variables.less +66 -0
- data/less-rails-jasny-bootstrap.gemspec +26 -0
- data/lib/less-rails-jasny-bootstrap.rb +11 -0
- data/lib/less/rails/jasny/bootstrap.rb +2 -0
- data/lib/less/rails/jasny/bootstrap/engine.rb +15 -0
- data/lib/less/rails/jasny/bootstrap/version.rb +9 -0
- metadata +144 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d4632ba265f1f100764317039bc7da7fe413677f
|
4
|
+
data.tar.gz: 1977d723517f4884b35bd261108951185e49fbcc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ac40c9da388ff9e00297fab9a35fe5f1c13f5bfb0b5bcf333fff350a945afc916231486338966ceeaf1431c83d6bf8d144e78c641cdef59b845dc323fc0d911d
|
7
|
+
data.tar.gz: 11d25a3eb7045c446dd7c9b678b78ade0d894a019b4e7b095c1c157ee432de6da7b0020e97a90114c5cfef0df1fe10277e9669a9c0e4b146760117bb58740e88
|
data/.gitignore
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
|
11
|
+
*.rbc
|
12
|
+
.rspec
|
13
|
+
/log
|
14
|
+
/tmp
|
15
|
+
/public/system
|
16
|
+
/spec/tmp
|
17
|
+
**.orig
|
18
|
+
|
19
|
+
|
20
|
+
## Environment normalisation:
|
21
|
+
/.bundle
|
22
|
+
/vendor/bundle
|
23
|
+
|
24
|
+
# these should all be checked in to normalise the environment:
|
25
|
+
# Gemfile.lock, .ruby-version, .ruby-gemset
|
26
|
+
|
27
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
28
|
+
.rvmrc
|
29
|
+
|
30
|
+
# if using bower-rails ignore default bower_components path bower.json files
|
31
|
+
/vendor/assets/bower_components
|
32
|
+
*.bowerrc
|
33
|
+
bower.json
|
34
|
+
|
35
|
+
# Ignore pow environment settings
|
36
|
+
.powenv
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Erich Quintero
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Erich Quintero
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Less Rails Jasny Bootstrap
|
2
|
+
|
3
|
+
|
4
|
+
The less-rails-jasny-bootstrap project makes [Jasny Bootstrap](http://jasny.github.io/bootstrap/)'s source LESS files, compiled CSS, and JavaScript files available in the Rails 3.x and 4.x asset pipeline.
|
5
|
+
|
6
|
+
The benefits:
|
7
|
+
|
8
|
+
* Assets are namespaced in yasny/bootstrap to avoid asset conflicts.
|
9
|
+
* Top level requires to get all stylesheets or javascripts.
|
10
|
+
* Ability to import or require individually namespaced stylesheets or javascripts.
|
11
|
+
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
LESS requires a JavaScript runtime to work. Which one you use depends on your Ruby implementation. Two are shown for Ruby (MRI) and JRuby. Add only the relevant one to your Gemfile. If you want to use Jasny Bootstrap's JavaScript plugins, also add the `jquery-rails` gem. Finally, add `less-rails-bootstrap and `less-jasny-rails-bootstrap` and run `bundle install`.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
# Gemfile
|
19
|
+
|
20
|
+
gem 'therubyracer' # If using Ruby
|
21
|
+
gem 'therubyrhino' # If using JRuby
|
22
|
+
gem 'jquery-rails' # If using Bootstrap's JS plugins.
|
23
|
+
gem 'less-rails-bootstrap'
|
24
|
+
gem 'less-jasny-rails-bootstrap'
|
25
|
+
```
|
26
|
+
|
27
|
+
## Basic CSS Use
|
28
|
+
|
29
|
+
### Simple way
|
30
|
+
|
31
|
+
Get the full Jasny Bootstrap stylesheet with a single line in your `application.css`.
|
32
|
+
|
33
|
+
```
|
34
|
+
/*
|
35
|
+
*= require jasny/bootstrap
|
36
|
+
*/
|
37
|
+
```
|
38
|
+
|
39
|
+
|
40
|
+
## Basic JavaScript Use
|
41
|
+
|
42
|
+
In `application.js`, require jQuery first. Now you can add all the Bootstrap and Jasny Bootstrap plugins with a single line.
|
43
|
+
|
44
|
+
````
|
45
|
+
//= require jquery
|
46
|
+
//= require jquery_ujs
|
47
|
+
//= require twitter/bootstrap
|
48
|
+
//= require jasny/bootstrap
|
49
|
+
````
|
50
|
+
|
51
|
+
Or include plugins individually.
|
52
|
+
|
53
|
+
````
|
54
|
+
//= require jquery
|
55
|
+
//= require jquery_ujs
|
56
|
+
//= require twitter/bootstrap
|
57
|
+
//= require jasny/bootstrap/offcanvas
|
58
|
+
````
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
|
62
|
+
1. Fork it
|
63
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
64
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
65
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
66
|
+
5. Create a new Pull Request
|
67
|
+
|
68
|
+
|
69
|
+
## Versioning
|
70
|
+
|
71
|
+
This gem will directly track the semantic versioning of the Jasny Bootstrap project. Our major and minor versions will always match to theirs, though we may have tiny patch level releases specific to this gem.
|
72
|
+
|
73
|
+
## License
|
74
|
+
|
75
|
+
[Twitter Bootstrap Project](https://github.com/twbs/bootstrap) - Copyright 2011-2015 Twitter, Inc. Code released under [the MIT license](https://github.com/twbs/bootstrap/blob/master/LICENSE). Docs released under [Creative Commons](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE).
|
76
|
+
|
77
|
+
[Less::Rails](https://github.com/metaskills/less-rails) and [Less::Rails::Bootstrap](https://github.com/metaskills/less-rails-bootstrap) - Copyright (c) 2011 Ken Collins, <ken@metaskills.net> and distributed under the MIT license.
|
78
|
+
|
79
|
+
[Jasny Bootstrap] - Copyright 2013 Jasny BV under [the Apache 2.0 license](LICENSE).
|
80
|
+
|
81
|
+
Distributed under MIT License.
|
data/Rakefile
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
/* ===========================================================
|
2
|
+
* Bootstrap: fileinput.js v3.1.3
|
3
|
+
* http://jasny.github.com/bootstrap/javascript/#fileinput
|
4
|
+
* ===========================================================
|
5
|
+
* Copyright 2012-2014 Arnold Daniels
|
6
|
+
*
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License")
|
8
|
+
* you may not use this file except in compliance with the License.
|
9
|
+
* You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
* ========================================================== */
|
19
|
+
|
20
|
+
+function ($) { "use strict";
|
21
|
+
|
22
|
+
var isIE = window.navigator.appName == 'Microsoft Internet Explorer'
|
23
|
+
|
24
|
+
// FILEUPLOAD PUBLIC CLASS DEFINITION
|
25
|
+
// =================================
|
26
|
+
|
27
|
+
var Fileinput = function (element, options) {
|
28
|
+
this.$element = $(element)
|
29
|
+
|
30
|
+
this.$input = this.$element.find(':file')
|
31
|
+
if (this.$input.length === 0) return
|
32
|
+
|
33
|
+
this.name = this.$input.attr('name') || options.name
|
34
|
+
|
35
|
+
this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
|
36
|
+
if (this.$hidden.length === 0) {
|
37
|
+
this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
|
38
|
+
}
|
39
|
+
|
40
|
+
this.$preview = this.$element.find('.fileinput-preview')
|
41
|
+
var height = this.$preview.css('height')
|
42
|
+
if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
|
43
|
+
this.$preview.css('line-height', height)
|
44
|
+
}
|
45
|
+
|
46
|
+
this.original = {
|
47
|
+
exists: this.$element.hasClass('fileinput-exists'),
|
48
|
+
preview: this.$preview.html(),
|
49
|
+
hiddenVal: this.$hidden.val()
|
50
|
+
}
|
51
|
+
|
52
|
+
this.listen()
|
53
|
+
}
|
54
|
+
|
55
|
+
Fileinput.prototype.listen = function() {
|
56
|
+
this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
|
57
|
+
$(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
|
58
|
+
|
59
|
+
this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
|
60
|
+
this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
|
61
|
+
},
|
62
|
+
|
63
|
+
Fileinput.prototype.change = function(e) {
|
64
|
+
var files = e.target.files === undefined ? (e.target && e.target.value ? [{ name: e.target.value.replace(/^.+\\/, '')}] : []) : e.target.files
|
65
|
+
|
66
|
+
e.stopPropagation()
|
67
|
+
|
68
|
+
if (files.length === 0) {
|
69
|
+
this.clear()
|
70
|
+
return
|
71
|
+
}
|
72
|
+
|
73
|
+
this.$hidden.val('')
|
74
|
+
this.$hidden.attr('name', '')
|
75
|
+
this.$input.attr('name', this.name)
|
76
|
+
|
77
|
+
var file = files[0]
|
78
|
+
|
79
|
+
if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg)$/) : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
|
80
|
+
var reader = new FileReader()
|
81
|
+
var preview = this.$preview
|
82
|
+
var element = this.$element
|
83
|
+
|
84
|
+
reader.onload = function(re) {
|
85
|
+
var $img = $('<img>')
|
86
|
+
$img[0].src = re.target.result
|
87
|
+
files[0].result = re.target.result
|
88
|
+
|
89
|
+
element.find('.fileinput-filename').text(file.name)
|
90
|
+
|
91
|
+
// if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
|
92
|
+
if (preview.css('max-height') != 'none') $img.css('max-height', parseInt(preview.css('max-height'), 10) - parseInt(preview.css('padding-top'), 10) - parseInt(preview.css('padding-bottom'), 10) - parseInt(preview.css('border-top'), 10) - parseInt(preview.css('border-bottom'), 10))
|
93
|
+
|
94
|
+
preview.html($img)
|
95
|
+
element.addClass('fileinput-exists').removeClass('fileinput-new')
|
96
|
+
|
97
|
+
element.trigger('change.bs.fileinput', files)
|
98
|
+
}
|
99
|
+
|
100
|
+
reader.readAsDataURL(file)
|
101
|
+
} else {
|
102
|
+
this.$element.find('.fileinput-filename').text(file.name)
|
103
|
+
this.$preview.text(file.name)
|
104
|
+
|
105
|
+
this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
|
106
|
+
|
107
|
+
this.$element.trigger('change.bs.fileinput')
|
108
|
+
}
|
109
|
+
},
|
110
|
+
|
111
|
+
Fileinput.prototype.clear = function(e) {
|
112
|
+
if (e) e.preventDefault()
|
113
|
+
|
114
|
+
this.$hidden.val('')
|
115
|
+
this.$hidden.attr('name', this.name)
|
116
|
+
this.$input.attr('name', '')
|
117
|
+
|
118
|
+
//ie8+ doesn't support changing the value of input with type=file so clone instead
|
119
|
+
if (isIE) {
|
120
|
+
var inputClone = this.$input.clone(true);
|
121
|
+
this.$input.after(inputClone);
|
122
|
+
this.$input.remove();
|
123
|
+
this.$input = inputClone;
|
124
|
+
} else {
|
125
|
+
this.$input.val('')
|
126
|
+
}
|
127
|
+
|
128
|
+
this.$preview.html('')
|
129
|
+
this.$element.find('.fileinput-filename').text('')
|
130
|
+
this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
|
131
|
+
|
132
|
+
if (e !== undefined) {
|
133
|
+
this.$input.trigger('change')
|
134
|
+
this.$element.trigger('clear.bs.fileinput')
|
135
|
+
}
|
136
|
+
},
|
137
|
+
|
138
|
+
Fileinput.prototype.reset = function() {
|
139
|
+
this.clear()
|
140
|
+
|
141
|
+
this.$hidden.val(this.original.hiddenVal)
|
142
|
+
this.$preview.html(this.original.preview)
|
143
|
+
this.$element.find('.fileinput-filename').text('')
|
144
|
+
|
145
|
+
if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
|
146
|
+
else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
|
147
|
+
|
148
|
+
this.$element.trigger('reset.bs.fileinput')
|
149
|
+
},
|
150
|
+
|
151
|
+
Fileinput.prototype.trigger = function(e) {
|
152
|
+
this.$input.trigger('click')
|
153
|
+
e.preventDefault()
|
154
|
+
}
|
155
|
+
|
156
|
+
|
157
|
+
// FILEUPLOAD PLUGIN DEFINITION
|
158
|
+
// ===========================
|
159
|
+
|
160
|
+
var old = $.fn.fileinput
|
161
|
+
|
162
|
+
$.fn.fileinput = function (options) {
|
163
|
+
return this.each(function () {
|
164
|
+
var $this = $(this),
|
165
|
+
data = $this.data('bs.fileinput')
|
166
|
+
if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
|
167
|
+
if (typeof options == 'string') data[options]()
|
168
|
+
})
|
169
|
+
}
|
170
|
+
|
171
|
+
$.fn.fileinput.Constructor = Fileinput
|
172
|
+
|
173
|
+
|
174
|
+
// FILEINPUT NO CONFLICT
|
175
|
+
// ====================
|
176
|
+
|
177
|
+
$.fn.fileinput.noConflict = function () {
|
178
|
+
$.fn.fileinput = old
|
179
|
+
return this
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
// FILEUPLOAD DATA-API
|
184
|
+
// ==================
|
185
|
+
|
186
|
+
$(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function (e) {
|
187
|
+
var $this = $(this)
|
188
|
+
if ($this.data('bs.fileinput')) return
|
189
|
+
$this.fileinput($this.data())
|
190
|
+
|
191
|
+
var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
|
192
|
+
if ($target.length > 0) {
|
193
|
+
e.preventDefault()
|
194
|
+
$target.trigger('click.bs.fileinput')
|
195
|
+
}
|
196
|
+
})
|
197
|
+
|
198
|
+
}(window.jQuery);
|
@@ -0,0 +1,360 @@
|
|
1
|
+
/* ===========================================================
|
2
|
+
* Bootstrap: inputmask.js v3.1.0
|
3
|
+
* http://jasny.github.io/bootstrap/javascript/#inputmask
|
4
|
+
*
|
5
|
+
* Based on Masked Input plugin by Josh Bush (digitalbush.com)
|
6
|
+
* ===========================================================
|
7
|
+
* Copyright 2012-2014 Arnold Daniels
|
8
|
+
*
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License")
|
10
|
+
* you may not use this file except in compliance with the License.
|
11
|
+
* You may obtain a copy of the License at
|
12
|
+
*
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
14
|
+
*
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
17
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
18
|
+
* See the License for the specific language governing permissions and
|
19
|
+
* limitations under the License.
|
20
|
+
* ========================================================== */
|
21
|
+
|
22
|
+
+function ($) { "use strict";
|
23
|
+
|
24
|
+
var isIphone = (window.orientation !== undefined)
|
25
|
+
var isAndroid = navigator.userAgent.toLowerCase().indexOf("android") > -1
|
26
|
+
var isIE = window.navigator.appName == 'Microsoft Internet Explorer'
|
27
|
+
|
28
|
+
// INPUTMASK PUBLIC CLASS DEFINITION
|
29
|
+
// =================================
|
30
|
+
|
31
|
+
var Inputmask = function (element, options) {
|
32
|
+
if (isAndroid) return // No support because caret positioning doesn't work on Android
|
33
|
+
|
34
|
+
this.$element = $(element)
|
35
|
+
this.options = $.extend({}, Inputmask.DEFAULTS, options)
|
36
|
+
this.mask = String(this.options.mask)
|
37
|
+
|
38
|
+
this.init()
|
39
|
+
this.listen()
|
40
|
+
|
41
|
+
this.checkVal() //Perform initial check for existing values
|
42
|
+
}
|
43
|
+
|
44
|
+
Inputmask.DEFAULTS = {
|
45
|
+
mask: "",
|
46
|
+
placeholder: "_",
|
47
|
+
definitions: {
|
48
|
+
'9': "[0-9]",
|
49
|
+
'a': "[A-Za-z]",
|
50
|
+
'w': "[A-Za-z0-9]",
|
51
|
+
'*': "."
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
Inputmask.prototype.init = function() {
|
56
|
+
var defs = this.options.definitions
|
57
|
+
var len = this.mask.length
|
58
|
+
|
59
|
+
this.tests = []
|
60
|
+
this.partialPosition = this.mask.length
|
61
|
+
this.firstNonMaskPos = null
|
62
|
+
|
63
|
+
$.each(this.mask.split(""), $.proxy(function(i, c) {
|
64
|
+
if (c == '?') {
|
65
|
+
len--
|
66
|
+
this.partialPosition = i
|
67
|
+
} else if (defs[c]) {
|
68
|
+
this.tests.push(new RegExp(defs[c]))
|
69
|
+
if (this.firstNonMaskPos === null)
|
70
|
+
this.firstNonMaskPos = this.tests.length - 1
|
71
|
+
} else {
|
72
|
+
this.tests.push(null)
|
73
|
+
}
|
74
|
+
}, this))
|
75
|
+
|
76
|
+
this.buffer = $.map(this.mask.split(""), $.proxy(function(c, i) {
|
77
|
+
if (c != '?') return defs[c] ? this.options.placeholder : c
|
78
|
+
}, this))
|
79
|
+
|
80
|
+
this.focusText = this.$element.val()
|
81
|
+
|
82
|
+
this.$element.data("rawMaskFn", $.proxy(function() {
|
83
|
+
return $.map(this.buffer, function(c, i) {
|
84
|
+
return this.tests[i] && c != this.options.placeholder ? c : null
|
85
|
+
}).join('')
|
86
|
+
}, this))
|
87
|
+
}
|
88
|
+
|
89
|
+
Inputmask.prototype.listen = function() {
|
90
|
+
if (this.$element.attr("readonly")) return
|
91
|
+
|
92
|
+
var pasteEventName = (isIE ? 'paste' : 'input') + ".mask"
|
93
|
+
|
94
|
+
this.$element
|
95
|
+
.on("unmask.bs.inputmask", $.proxy(this.unmask, this))
|
96
|
+
|
97
|
+
.on("focus.bs.inputmask", $.proxy(this.focusEvent, this))
|
98
|
+
.on("blur.bs.inputmask", $.proxy(this.blurEvent, this))
|
99
|
+
|
100
|
+
.on("keydown.bs.inputmask", $.proxy(this.keydownEvent, this))
|
101
|
+
.on("keypress.bs.inputmask", $.proxy(this.keypressEvent, this))
|
102
|
+
|
103
|
+
.on(pasteEventName, $.proxy(this.pasteEvent, this))
|
104
|
+
}
|
105
|
+
|
106
|
+
//Helper Function for Caret positioning
|
107
|
+
Inputmask.prototype.caret = function(begin, end) {
|
108
|
+
if (this.$element.length === 0) return
|
109
|
+
if (typeof begin == 'number') {
|
110
|
+
end = (typeof end == 'number') ? end : begin
|
111
|
+
return this.$element.each(function() {
|
112
|
+
if (this.setSelectionRange) {
|
113
|
+
this.setSelectionRange(begin, end)
|
114
|
+
} else if (this.createTextRange) {
|
115
|
+
var range = this.createTextRange()
|
116
|
+
range.collapse(true)
|
117
|
+
range.moveEnd('character', end)
|
118
|
+
range.moveStart('character', begin)
|
119
|
+
range.select()
|
120
|
+
}
|
121
|
+
})
|
122
|
+
} else {
|
123
|
+
if (this.$element[0].setSelectionRange) {
|
124
|
+
begin = this.$element[0].selectionStart
|
125
|
+
end = this.$element[0].selectionEnd
|
126
|
+
} else if (document.selection && document.selection.createRange) {
|
127
|
+
var range = document.selection.createRange()
|
128
|
+
begin = 0 - range.duplicate().moveStart('character', -100000)
|
129
|
+
end = begin + range.text.length
|
130
|
+
}
|
131
|
+
return {
|
132
|
+
begin: begin,
|
133
|
+
end: end
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
Inputmask.prototype.seekNext = function(pos) {
|
139
|
+
var len = this.mask.length
|
140
|
+
while (++pos <= len && !this.tests[pos]);
|
141
|
+
|
142
|
+
return pos
|
143
|
+
}
|
144
|
+
|
145
|
+
Inputmask.prototype.seekPrev = function(pos) {
|
146
|
+
while (--pos >= 0 && !this.tests[pos]);
|
147
|
+
|
148
|
+
return pos
|
149
|
+
}
|
150
|
+
|
151
|
+
Inputmask.prototype.shiftL = function(begin,end) {
|
152
|
+
var len = this.mask.length
|
153
|
+
|
154
|
+
if (begin < 0) return
|
155
|
+
|
156
|
+
for (var i = begin, j = this.seekNext(end); i < len; i++) {
|
157
|
+
if (this.tests[i]) {
|
158
|
+
if (j < len && this.tests[i].test(this.buffer[j])) {
|
159
|
+
this.buffer[i] = this.buffer[j]
|
160
|
+
this.buffer[j] = this.options.placeholder
|
161
|
+
} else
|
162
|
+
break
|
163
|
+
j = this.seekNext(j)
|
164
|
+
}
|
165
|
+
}
|
166
|
+
this.writeBuffer()
|
167
|
+
this.caret(Math.max(this.firstNonMaskPos, begin))
|
168
|
+
}
|
169
|
+
|
170
|
+
Inputmask.prototype.shiftR = function(pos) {
|
171
|
+
var len = this.mask.length
|
172
|
+
|
173
|
+
for (var i = pos, c = this.options.placeholder; i < len; i++) {
|
174
|
+
if (this.tests[i]) {
|
175
|
+
var j = this.seekNext(i)
|
176
|
+
var t = this.buffer[i]
|
177
|
+
this.buffer[i] = c
|
178
|
+
if (j < len && this.tests[j].test(t))
|
179
|
+
c = t
|
180
|
+
else
|
181
|
+
break
|
182
|
+
}
|
183
|
+
}
|
184
|
+
},
|
185
|
+
|
186
|
+
Inputmask.prototype.unmask = function() {
|
187
|
+
this.$element
|
188
|
+
.unbind(".mask")
|
189
|
+
.removeData("inputmask")
|
190
|
+
}
|
191
|
+
|
192
|
+
Inputmask.prototype.focusEvent = function() {
|
193
|
+
this.focusText = this.$element.val()
|
194
|
+
var len = this.mask.length
|
195
|
+
var pos = this.checkVal()
|
196
|
+
this.writeBuffer()
|
197
|
+
|
198
|
+
var that = this
|
199
|
+
var moveCaret = function() {
|
200
|
+
if (pos == len)
|
201
|
+
that.caret(0, pos)
|
202
|
+
else
|
203
|
+
that.caret(pos)
|
204
|
+
}
|
205
|
+
|
206
|
+
moveCaret()
|
207
|
+
setTimeout(moveCaret, 50)
|
208
|
+
}
|
209
|
+
|
210
|
+
Inputmask.prototype.blurEvent = function() {
|
211
|
+
this.checkVal()
|
212
|
+
if (this.$element.val() !== this.focusText)
|
213
|
+
this.$element.trigger('change')
|
214
|
+
}
|
215
|
+
|
216
|
+
Inputmask.prototype.keydownEvent = function(e) {
|
217
|
+
var k = e.which
|
218
|
+
|
219
|
+
//backspace, delete, and escape get special treatment
|
220
|
+
if (k == 8 || k == 46 || (isIphone && k == 127)) {
|
221
|
+
var pos = this.caret(),
|
222
|
+
begin = pos.begin,
|
223
|
+
end = pos.end
|
224
|
+
|
225
|
+
if (end - begin === 0) {
|
226
|
+
begin = k != 46 ? this.seekPrev(begin) : (end = this.seekNext(begin - 1))
|
227
|
+
end = k == 46 ? this.seekNext(end) : end
|
228
|
+
}
|
229
|
+
this.clearBuffer(begin, end)
|
230
|
+
this.shiftL(begin, end - 1)
|
231
|
+
|
232
|
+
return false
|
233
|
+
} else if (k == 27) {//escape
|
234
|
+
this.$element.val(this.focusText)
|
235
|
+
this.caret(0, this.checkVal())
|
236
|
+
return false
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
Inputmask.prototype.keypressEvent = function(e) {
|
241
|
+
var len = this.mask.length
|
242
|
+
|
243
|
+
var k = e.which,
|
244
|
+
pos = this.caret()
|
245
|
+
|
246
|
+
if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
|
247
|
+
return true
|
248
|
+
} else if (k) {
|
249
|
+
if (pos.end - pos.begin !== 0) {
|
250
|
+
this.clearBuffer(pos.begin, pos.end)
|
251
|
+
this.shiftL(pos.begin, pos.end - 1)
|
252
|
+
}
|
253
|
+
|
254
|
+
var p = this.seekNext(pos.begin - 1)
|
255
|
+
if (p < len) {
|
256
|
+
var c = String.fromCharCode(k)
|
257
|
+
if (this.tests[p].test(c)) {
|
258
|
+
this.shiftR(p)
|
259
|
+
this.buffer[p] = c
|
260
|
+
this.writeBuffer()
|
261
|
+
var next = this.seekNext(p)
|
262
|
+
this.caret(next)
|
263
|
+
}
|
264
|
+
}
|
265
|
+
return false
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
Inputmask.prototype.pasteEvent = function() {
|
270
|
+
var that = this
|
271
|
+
|
272
|
+
setTimeout(function() {
|
273
|
+
that.caret(that.checkVal(true))
|
274
|
+
}, 0)
|
275
|
+
}
|
276
|
+
|
277
|
+
Inputmask.prototype.clearBuffer = function(start, end) {
|
278
|
+
var len = this.mask.length
|
279
|
+
|
280
|
+
for (var i = start; i < end && i < len; i++) {
|
281
|
+
if (this.tests[i])
|
282
|
+
this.buffer[i] = this.options.placeholder
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
Inputmask.prototype.writeBuffer = function() {
|
287
|
+
return this.$element.val(this.buffer.join('')).val()
|
288
|
+
}
|
289
|
+
|
290
|
+
Inputmask.prototype.checkVal = function(allow) {
|
291
|
+
var len = this.mask.length
|
292
|
+
//try to place characters where they belong
|
293
|
+
var test = this.$element.val()
|
294
|
+
var lastMatch = -1
|
295
|
+
|
296
|
+
for (var i = 0, pos = 0; i < len; i++) {
|
297
|
+
if (this.tests[i]) {
|
298
|
+
this.buffer[i] = this.options.placeholder
|
299
|
+
while (pos++ < test.length) {
|
300
|
+
var c = test.charAt(pos - 1)
|
301
|
+
if (this.tests[i].test(c)) {
|
302
|
+
this.buffer[i] = c
|
303
|
+
lastMatch = i
|
304
|
+
break
|
305
|
+
}
|
306
|
+
}
|
307
|
+
if (pos > test.length)
|
308
|
+
break
|
309
|
+
} else if (this.buffer[i] == test.charAt(pos) && i != this.partialPosition) {
|
310
|
+
pos++
|
311
|
+
lastMatch = i
|
312
|
+
}
|
313
|
+
}
|
314
|
+
if (!allow && lastMatch + 1 < this.partialPosition) {
|
315
|
+
this.$element.val("")
|
316
|
+
this.clearBuffer(0, len)
|
317
|
+
} else if (allow || lastMatch + 1 >= this.partialPosition) {
|
318
|
+
this.writeBuffer()
|
319
|
+
if (!allow) this.$element.val(this.$element.val().substring(0, lastMatch + 1))
|
320
|
+
}
|
321
|
+
return (this.partialPosition ? i : this.firstNonMaskPos)
|
322
|
+
}
|
323
|
+
|
324
|
+
|
325
|
+
// INPUTMASK PLUGIN DEFINITION
|
326
|
+
// ===========================
|
327
|
+
|
328
|
+
var old = $.fn.inputmask
|
329
|
+
|
330
|
+
$.fn.inputmask = function (options) {
|
331
|
+
return this.each(function () {
|
332
|
+
var $this = $(this)
|
333
|
+
var data = $this.data('bs.inputmask')
|
334
|
+
|
335
|
+
if (!data) $this.data('bs.inputmask', (data = new Inputmask(this, options)))
|
336
|
+
})
|
337
|
+
}
|
338
|
+
|
339
|
+
$.fn.inputmask.Constructor = Inputmask
|
340
|
+
|
341
|
+
|
342
|
+
// INPUTMASK NO CONFLICT
|
343
|
+
// ====================
|
344
|
+
|
345
|
+
$.fn.inputmask.noConflict = function () {
|
346
|
+
$.fn.inputmask = old
|
347
|
+
return this
|
348
|
+
}
|
349
|
+
|
350
|
+
|
351
|
+
// INPUTMASK DATA-API
|
352
|
+
// ==================
|
353
|
+
|
354
|
+
$(document).on('focus.bs.inputmask.data-api', '[data-mask]', function (e) {
|
355
|
+
var $this = $(this)
|
356
|
+
if ($this.data('bs.inputmask')) return
|
357
|
+
$this.inputmask($this.data())
|
358
|
+
})
|
359
|
+
|
360
|
+
}(window.jQuery);
|