less-rails-jasny-bootstrap 3.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/CODE_OF_CONDUCT.md +13 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +22 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +81 -0
  8. data/Rakefile +2 -0
  9. data/app/assets/javascripts/jasny/bootstrap/fileinput.js +198 -0
  10. data/app/assets/javascripts/jasny/bootstrap/inputmask.js +360 -0
  11. data/app/assets/javascripts/jasny/bootstrap/offcanvas.js +318 -0
  12. data/app/assets/javascripts/jasny/bootstrap/rowlink.js +86 -0
  13. data/app/assets/javascripts/jasny/bootstrap/transition.js +50 -0
  14. data/app/assets/javascripts/jasny/jasny-bootstrap.js +5 -0
  15. data/app/assets/stylesheets/jasny/jasny-bootstrap.less +1 -0
  16. data/app/frameworks/jasny/bootstrap/alerts-fixed.less +39 -0
  17. data/app/frameworks/jasny/bootstrap/build/jasny-bootstrap.less +5 -0
  18. data/app/frameworks/jasny/bootstrap/build/mixins.less +61 -0
  19. data/app/frameworks/jasny/bootstrap/build/variables.less +216 -0
  20. data/app/frameworks/jasny/bootstrap/button-labels.less +38 -0
  21. data/app/frameworks/jasny/bootstrap/fileinput.less +122 -0
  22. data/app/frameworks/jasny/bootstrap/grid-container-smooth.less +10 -0
  23. data/app/frameworks/jasny/bootstrap/jasny-bootstrap.less +18 -0
  24. data/app/frameworks/jasny/bootstrap/nav-tab-alignment.less +97 -0
  25. data/app/frameworks/jasny/bootstrap/navmenu.less +273 -0
  26. data/app/frameworks/jasny/bootstrap/offcanvas.less +48 -0
  27. data/app/frameworks/jasny/bootstrap/rowlink.less +22 -0
  28. data/app/frameworks/jasny/bootstrap/variables.less +66 -0
  29. data/less-rails-jasny-bootstrap.gemspec +26 -0
  30. data/lib/less-rails-jasny-bootstrap.rb +11 -0
  31. data/lib/less/rails/jasny/bootstrap.rb +2 -0
  32. data/lib/less/rails/jasny/bootstrap/engine.rb +15 -0
  33. data/lib/less/rails/jasny/bootstrap/version.rb +9 -0
  34. 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
@@ -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
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in less-rails-jasny-bootstrap.gemspec
4
+ gemspec
5
+
6
+ gem 'therubyracer', '>= 0.10.1', :require => nil, :platforms => :ruby
7
+ gem 'therubyrhino', '>= 1.73.2', :require => nil, :platforms => :jruby
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,2 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
@@ -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);