rails-bootstrap-material-design 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +18 -0
  4. data/Rakefile +1 -0
  5. data/app/.DS_Store +0 -0
  6. data/app/assets/.DS_Store +0 -0
  7. data/app/assets/images/.DS_Store +0 -0
  8. data/app/assets/images/bootstrap-material-design/material-design-color-palette.jpg +0 -0
  9. data/app/assets/javascripts/.DS_Store +0 -0
  10. data/app/assets/javascripts/bootstrap-material-design.js +2 -0
  11. data/app/assets/javascripts/bootstrap-material-design/material.js +350 -0
  12. data/app/assets/javascripts/bootstrap-material-design/ripples.js +325 -0
  13. data/app/assets/stylesheets/.DS_Store +0 -0
  14. data/app/assets/stylesheets/bootstrap-material-design.scss +4 -0
  15. data/app/assets/stylesheets/bootstrap-material-design/.DS_Store +0 -0
  16. data/app/assets/stylesheets/bootstrap-material-design/_alerts.scss +17 -0
  17. data/app/assets/stylesheets/bootstrap-material-design/_buttons.scss +244 -0
  18. data/app/assets/stylesheets/bootstrap-material-design/_cards.scss +66 -0
  19. data/app/assets/stylesheets/bootstrap-material-design/_checkboxes.scss +270 -0
  20. data/app/assets/stylesheets/bootstrap-material-design/_colors-map.scss +311 -0
  21. data/app/assets/stylesheets/bootstrap-material-design/_colors.scss +359 -0
  22. data/app/assets/stylesheets/bootstrap-material-design/_core.scss +93 -0
  23. data/app/assets/stylesheets/bootstrap-material-design/_dialogs.scss +52 -0
  24. data/app/assets/stylesheets/bootstrap-material-design/_dividers.scss +71 -0
  25. data/app/assets/stylesheets/bootstrap-material-design/_form.scss +40 -0
  26. data/app/assets/stylesheets/bootstrap-material-design/_import-bs-sass.scss +2 -0
  27. data/app/assets/stylesheets/bootstrap-material-design/_inputs-size.scss +221 -0
  28. data/app/assets/stylesheets/bootstrap-material-design/_inputs.scss +352 -0
  29. data/app/assets/stylesheets/bootstrap-material-design/_labels.scss +4 -0
  30. data/app/assets/stylesheets/bootstrap-material-design/_lists.scss +102 -0
  31. data/app/assets/stylesheets/bootstrap-material-design/_mixins-utilities.scss +31 -0
  32. data/app/assets/stylesheets/bootstrap-material-design/_mixins.scss +241 -0
  33. data/app/assets/stylesheets/bootstrap-material-design/_navbar.scss +232 -0
  34. data/app/assets/stylesheets/bootstrap-material-design/_panels.scss +21 -0
  35. data/app/assets/stylesheets/bootstrap-material-design/_plugins.scss +5 -0
  36. data/app/assets/stylesheets/bootstrap-material-design/_popups.scss +18 -0
  37. data/app/assets/stylesheets/bootstrap-material-design/_progress.scss +10 -0
  38. data/app/assets/stylesheets/bootstrap-material-design/_radios.scss +115 -0
  39. data/app/assets/stylesheets/bootstrap-material-design/_shadows.scss +82 -0
  40. data/app/assets/stylesheets/bootstrap-material-design/_table.scss +15 -0
  41. data/app/assets/stylesheets/bootstrap-material-design/_tabs.scss +24 -0
  42. data/app/assets/stylesheets/bootstrap-material-design/_themes.scss +6 -0
  43. data/app/assets/stylesheets/bootstrap-material-design/_togglebutton.scss +83 -0
  44. data/app/assets/stylesheets/bootstrap-material-design/_typography.scss +15 -0
  45. data/app/assets/stylesheets/bootstrap-material-design/_variables.scss +169 -0
  46. data/app/assets/stylesheets/bootstrap-material-design/_welljumbo.scss +26 -0
  47. data/app/assets/stylesheets/bootstrap-material-design/plugins/_plugin-dropdownjs.scss +15 -0
  48. data/app/assets/stylesheets/bootstrap-material-design/plugins/_plugin-nouislider.scss +110 -0
  49. data/app/assets/stylesheets/bootstrap-material-design/plugins/_plugin-selectize.scss +91 -0
  50. data/app/assets/stylesheets/bootstrap-material-design/plugins/_plugin-snackbarjs.scss +32 -0
  51. data/app/assets/stylesheets/bootstrap-material-design/ripples.scss +36 -0
  52. data/lib/rails-bootstrap-material-design.rb +25 -0
  53. data/lib/rails-bootstrap-material-design/version.rb +3 -0
  54. data/rails-bootstrap-material-design.gemspec +20 -0
  55. metadata +124 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 39fe8854485ed92b3141763acafcefd3316f7f50
4
+ data.tar.gz: 3e86639bf27c03bcc79719aac300cfdc8bbe271c
5
+ SHA512:
6
+ metadata.gz: e7d18f4c71837c68b30fb9c5800b2970f7a632fbfe1bec64c1898b47daaa63d58a48e89ca20ce1662bde0bbcfac0d3961f0725bb22b7b6713c8a7e97fb11bf48
7
+ data.tar.gz: 7a943308fa14ac1f76994caa2c28ca17733013379a6775354e6e5dfcbf08bf5efe8f2879e7681e097f6888ae8382db6fa32a13666f5312c6c55125bf46c89ffd
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ source 'https://rails-assets.org'
3
+
4
+ gemspec
@@ -0,0 +1,18 @@
1
+ # rails-bootstrap-material-design
2
+
3
+ ## Usage
4
+
5
+ Add rails-assets source block to your `Gemfile`:
6
+
7
+ ```ruby
8
+ source "https://rails-assets.org" do
9
+ gem "rails-assets-bootstrap-material-design"
10
+ end
11
+
12
+ ```
13
+
14
+ Then, import the asset using Sprockets’ `require` directive:
15
+
16
+ ```js
17
+ //= require "bootstrap-material-design"
18
+ ```
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
Binary file
Binary file
@@ -0,0 +1,2 @@
1
+ //= require bootstrap-material-design/material.js
2
+ //= require bootstrap-material-design/ripples.js
@@ -0,0 +1,350 @@
1
+ /* globals jQuery */
2
+
3
+ (function($) {
4
+ // Selector to select only not already processed elements
5
+ $.expr[":"].notmdproc = function(obj) {
6
+ if ($(obj).data("mdproc")) {
7
+ return false;
8
+ } else {
9
+ return true;
10
+ }
11
+ };
12
+
13
+ function _isChar(evt) {
14
+ if (typeof evt.which == "undefined") {
15
+ return true;
16
+ } else if (typeof evt.which == "number" && evt.which > 0) {
17
+ return (
18
+ !evt.ctrlKey
19
+ && !evt.metaKey
20
+ && !evt.altKey
21
+ && evt.which != 8 // backspace
22
+ && evt.which != 9 // tab
23
+ && evt.which != 13 // enter
24
+ && evt.which != 16 // shift
25
+ && evt.which != 17 // ctrl
26
+ && evt.which != 20 // caps lock
27
+ && evt.which != 27 // escape
28
+ );
29
+ }
30
+ return false;
31
+ }
32
+
33
+ function _addFormGroupFocus(element) {
34
+ var $element = $(element);
35
+ if (!$element.prop('disabled')) { // this is showing as undefined on chrome but works fine on firefox??
36
+ $element.closest(".form-group").addClass("is-focused");
37
+ }
38
+ }
39
+
40
+ function _toggleDisabledState($element, state) {
41
+ var $target;
42
+ if ($element.hasClass('checkbox-inline') || $element.hasClass('radio-inline')) {
43
+ $target = $element;
44
+ } else {
45
+ $target = $element.closest('.checkbox').length ? $element.closest('.checkbox') : $element.closest('.radio');
46
+ }
47
+ return $target.toggleClass('disabled', state);
48
+ }
49
+
50
+ function _toggleTypeFocus($input) {
51
+ var disabledToggleType = false;
52
+ if ($input.is($.material.options.checkboxElements) || $input.is($.material.options.radioElements)) {
53
+ disabledToggleType = true;
54
+ }
55
+ $input.closest('label').hover(function() {
56
+ var $i = $(this).find('input');
57
+ var isDisabled = $i.prop('disabled'); // hack because the _addFormGroupFocus() wasn't identifying the property on chrome
58
+ if (disabledToggleType) {
59
+ _toggleDisabledState($(this), isDisabled);
60
+ }
61
+ if (!isDisabled) {
62
+ _addFormGroupFocus($i); // need to find the input so we can check disablement
63
+ }
64
+ },
65
+ function() {
66
+ _removeFormGroupFocus($(this).find('input'));
67
+ });
68
+ }
69
+
70
+ function _removeFormGroupFocus(element) {
71
+ $(element).closest(".form-group").removeClass("is-focused"); // remove class from form-group
72
+ }
73
+
74
+ $.material = {
75
+ "options": {
76
+ // These options set what will be started by $.material.init()
77
+ "validate": true,
78
+ "input": true,
79
+ "ripples": true,
80
+ "checkbox": true,
81
+ "togglebutton": true,
82
+ "radio": true,
83
+ "arrive": true,
84
+ "autofill": false,
85
+
86
+ "withRipples": [
87
+ ".btn:not(.btn-link)",
88
+ ".card-image",
89
+ ".navbar a:not(.withoutripple)",
90
+ ".dropdown-menu a",
91
+ ".nav-tabs a:not(.withoutripple)",
92
+ ".withripple",
93
+ ".pagination li:not(.active):not(.disabled) a:not(.withoutripple)"
94
+ ].join(","),
95
+ "inputElements": "input.form-control, textarea.form-control, select.form-control",
96
+ "checkboxElements": ".checkbox > label > input[type=checkbox], label.checkbox-inline > input[type=checkbox]",
97
+ "togglebuttonElements": ".togglebutton > label > input[type=checkbox]",
98
+ "radioElements": ".radio > label > input[type=radio], label.radio-inline > input[type=radio]"
99
+ },
100
+ "checkbox": function(selector) {
101
+ // Add fake-checkbox to material checkboxes
102
+ var $input = $((selector) ? selector : this.options.checkboxElements)
103
+ .filter(":notmdproc")
104
+ .data("mdproc", true)
105
+ .after("<span class='checkbox-material'><span class='check'></span></span>");
106
+
107
+ _toggleTypeFocus($input);
108
+ },
109
+ "togglebutton": function(selector) {
110
+ // Add fake-checkbox to material checkboxes
111
+ var $input = $((selector) ? selector : this.options.togglebuttonElements)
112
+ .filter(":notmdproc")
113
+ .data("mdproc", true)
114
+ .after("<span class='toggle'></span>");
115
+
116
+ _toggleTypeFocus($input);
117
+ },
118
+ "radio": function(selector) {
119
+ // Add fake-radio to material radios
120
+ var $input = $((selector) ? selector : this.options.radioElements)
121
+ .filter(":notmdproc")
122
+ .data("mdproc", true)
123
+ .after("<span class='circle'></span><span class='check'></span>");
124
+
125
+ _toggleTypeFocus($input);
126
+ },
127
+ "input": function(selector) {
128
+ $((selector) ? selector : this.options.inputElements)
129
+ .filter(":notmdproc")
130
+ .data("mdproc", true)
131
+ .each(function() {
132
+ var $input = $(this);
133
+
134
+ // Requires form-group standard markup (will add it if necessary)
135
+ var $formGroup = $input.closest(".form-group"); // note that form-group may be grandparent in the case of an input-group
136
+ if ($formGroup.length === 0 && $input.attr('type') !== "hidden" && !$input.attr('hidden')) {
137
+ $input.wrap("<div class='form-group'></div>");
138
+ $formGroup = $input.closest(".form-group"); // find node after attached (otherwise additional attachments don't work)
139
+ }
140
+
141
+ // Legacy - Add hint label if using the old shorthand data-hint attribute on the input
142
+ if ($input.attr("data-hint")) {
143
+ $input.after("<p class='help-block'>" + $input.attr("data-hint") + "</p>");
144
+ $input.removeAttr("data-hint");
145
+ }
146
+
147
+ // Legacy - Change input-sm/lg to form-group-sm/lg instead (preferred standard and simpler css/less variants)
148
+ var legacySizes = {
149
+ "input-lg": "form-group-lg",
150
+ "input-sm": "form-group-sm"
151
+ };
152
+ $.each(legacySizes, function(legacySize, standardSize) {
153
+ if ($input.hasClass(legacySize)) {
154
+ $input.removeClass(legacySize);
155
+ $formGroup.addClass(standardSize);
156
+ }
157
+ });
158
+
159
+ // Legacy - Add label-floating if using old shorthand <input class="floating-label" placeholder="foo">
160
+ if ($input.hasClass("floating-label")) {
161
+ var placeholder = $input.attr("placeholder");
162
+ $input.attr("placeholder", null).removeClass("floating-label");
163
+ var id = $input.attr("id");
164
+ var forAttribute = "";
165
+ if (id) {
166
+ forAttribute = "for='" + id + "'";
167
+ }
168
+ $formGroup.addClass("label-floating");
169
+ $input.after("<label " + forAttribute + "class='control-label'>" + placeholder + "</label>");
170
+ }
171
+
172
+ // Set as empty if is empty (damn I must improve this...)
173
+ if ($input.val() === null || $input.val() == "undefined" || $input.val() === "") {
174
+ $formGroup.addClass("is-empty");
175
+ }
176
+
177
+ // Support for file input
178
+ if ($formGroup.find("input[type=file]").length > 0) {
179
+ $formGroup.addClass("is-fileinput");
180
+ }
181
+ });
182
+ },
183
+ "attachInputEventHandlers": function() {
184
+ var validate = this.options.validate;
185
+
186
+ $(document)
187
+ .on("keydown paste", ".form-control", function(e) {
188
+ if (_isChar(e)) {
189
+ $(this).closest(".form-group").removeClass("is-empty");
190
+ }
191
+ })
192
+ .on("keyup change", ".form-control", function() {
193
+ var $input = $(this);
194
+ var $formGroup = $input.closest(".form-group");
195
+ var isValid = (typeof $input[0].checkValidity === "undefined" || $input[0].checkValidity());
196
+
197
+ if ($input.val() === "") {
198
+ $formGroup.addClass("is-empty");
199
+ } else {
200
+ $formGroup.removeClass("is-empty");
201
+ }
202
+
203
+ // Validation events do not bubble, so they must be attached directly to the input: http://jsfiddle.net/PEpRM/1/
204
+ // Further, even the bind method is being caught, but since we are already calling #checkValidity here, just alter
205
+ // the form-group on change.
206
+ //
207
+ // NOTE: I'm not sure we should be intervening regarding validation, this seems better as a README and snippet of code.
208
+ // BUT, I've left it here for backwards compatibility.
209
+ if (validate) {
210
+ if (isValid) {
211
+ $formGroup.removeClass("has-error");
212
+ } else {
213
+ $formGroup.addClass("has-error");
214
+ }
215
+ }
216
+ })
217
+ .on("focus", ".form-control, .form-group.is-fileinput", function() {
218
+ _addFormGroupFocus(this);
219
+ })
220
+ .on("blur", ".form-control, .form-group.is-fileinput", function() {
221
+ _removeFormGroupFocus(this);
222
+ })
223
+ // make sure empty is added back when there is a programmatic value change.
224
+ // NOTE: programmatic changing of value using $.val() must trigger the change event i.e. $.val('x').trigger('change')
225
+ .on("change", ".form-group input", function() {
226
+ var $input = $(this);
227
+ if ($input.attr("type") == "file") {
228
+ return;
229
+ }
230
+
231
+ var $formGroup = $input.closest(".form-group");
232
+ var value = $input.val();
233
+ if (value) {
234
+ $formGroup.removeClass("is-empty");
235
+ } else {
236
+ $formGroup.addClass("is-empty");
237
+ }
238
+ })
239
+ // set the fileinput readonly field with the name of the file
240
+ .on("change", ".form-group.is-fileinput input[type='file']", function() {
241
+ var $input = $(this);
242
+ var $formGroup = $input.closest(".form-group");
243
+ var value = "";
244
+ $.each(this.files, function(i, file) {
245
+ value += file.name + ", ";
246
+ });
247
+ value = value.substring(0, value.length - 2);
248
+ if (value) {
249
+ $formGroup.removeClass("is-empty");
250
+ } else {
251
+ $formGroup.addClass("is-empty");
252
+ }
253
+ $formGroup.find("input.form-control[readonly]").val(value);
254
+ });
255
+ },
256
+ "ripples": function(selector) {
257
+ $((selector) ? selector : this.options.withRipples).ripples();
258
+ },
259
+ "autofill": function() {
260
+ // This part of code will detect autofill when the page is loading (username and password inputs for example)
261
+ var loading = setInterval(function() {
262
+ $("input[type!=checkbox]").each(function() {
263
+ var $this = $(this);
264
+ if ($this.val() && $this.val() !== $this.attr("value")) {
265
+ $this.trigger("change");
266
+ }
267
+ });
268
+ }, 100);
269
+
270
+ // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
271
+ setTimeout(function() {
272
+ clearInterval(loading);
273
+ }, 10000);
274
+ },
275
+ "attachAutofillEventHandlers": function() {
276
+ // Listen on inputs of the focused form (because user can select from the autofill dropdown only when the input has focus)
277
+ var focused;
278
+ $(document)
279
+ .on("focus", "input", function() {
280
+ var $inputs = $(this).parents("form").find("input").not("[type=file]");
281
+ focused = setInterval(function() {
282
+ $inputs.each(function() {
283
+ var $this = $(this);
284
+ if ($this.val() !== $this.attr("value")) {
285
+ $this.trigger("change");
286
+ }
287
+ });
288
+ }, 100);
289
+ })
290
+ .on("blur", ".form-group input", function() {
291
+ clearInterval(focused);
292
+ });
293
+ },
294
+ "init": function(options) {
295
+ this.options = $.extend({}, this.options, options);
296
+ var $document = $(document);
297
+
298
+ if ($.fn.ripples && this.options.ripples) {
299
+ this.ripples();
300
+ }
301
+ if (this.options.input) {
302
+ this.input();
303
+ this.attachInputEventHandlers();
304
+ }
305
+ if (this.options.checkbox) {
306
+ this.checkbox();
307
+ }
308
+ if (this.options.togglebutton) {
309
+ this.togglebutton();
310
+ }
311
+ if (this.options.radio) {
312
+ this.radio();
313
+ }
314
+ if (this.options.autofill) {
315
+ this.autofill();
316
+ this.attachAutofillEventHandlers();
317
+ }
318
+
319
+ if (document.arrive && this.options.arrive) {
320
+ if ($.fn.ripples && this.options.ripples) {
321
+ $document.arrive(this.options.withRipples, function() {
322
+ $.material.ripples($(this));
323
+ });
324
+ }
325
+ if (this.options.input) {
326
+ $document.arrive(this.options.inputElements, function() {
327
+ $.material.input($(this));
328
+ });
329
+ }
330
+ if (this.options.checkbox) {
331
+ $document.arrive(this.options.checkboxElements, function() {
332
+ $.material.checkbox($(this));
333
+ });
334
+ }
335
+ if (this.options.radio) {
336
+ $document.arrive(this.options.radioElements, function() {
337
+ $.material.radio($(this));
338
+ });
339
+ }
340
+ if (this.options.togglebutton) {
341
+ $document.arrive(this.options.togglebuttonElements, function() {
342
+ $.material.togglebutton($(this));
343
+ });
344
+ }
345
+
346
+ }
347
+ }
348
+ };
349
+
350
+ })(jQuery);
@@ -0,0 +1,325 @@
1
+ /* Copyright 2014+, Federico Zivolo, LICENSE at https://github.com/FezVrasta/bootstrap-material-design/blob/master/LICENSE.md */
2
+ /* globals jQuery, navigator */
3
+
4
+ (function($, window, document, undefined) {
5
+
6
+ "use strict";
7
+
8
+ /**
9
+ * Define the name of the plugin
10
+ */
11
+ var ripples = "ripples";
12
+
13
+
14
+ /**
15
+ * Get an instance of the plugin
16
+ */
17
+ var self = null;
18
+
19
+
20
+ /**
21
+ * Define the defaults of the plugin
22
+ */
23
+ var defaults = {};
24
+
25
+
26
+ /**
27
+ * Create the main plugin function
28
+ */
29
+ function Ripples(element, options) {
30
+ self = this;
31
+
32
+ this.element = $(element);
33
+
34
+ this.options = $.extend({}, defaults, options);
35
+
36
+ this._defaults = defaults;
37
+ this._name = ripples;
38
+
39
+ this.init();
40
+ }
41
+
42
+
43
+ /**
44
+ * Initialize the plugin
45
+ */
46
+ Ripples.prototype.init = function() {
47
+ var $element = this.element;
48
+
49
+ $element.on("mousedown touchstart", function(event) {
50
+ /**
51
+ * Verify if the user is just touching on a device and return if so
52
+ */
53
+ if (self.isTouch() && event.type === "mousedown") {
54
+ return;
55
+ }
56
+
57
+
58
+ /**
59
+ * Verify if the current element already has a ripple wrapper element and
60
+ * creates if it doesn't
61
+ */
62
+ if (!($element.find(".ripple-container").length)) {
63
+ $element.append("<div class=\"ripple-container\"></div>");
64
+ }
65
+
66
+
67
+ /**
68
+ * Find the ripple wrapper
69
+ */
70
+ var $wrapper = $element.children(".ripple-container");
71
+
72
+
73
+ /**
74
+ * Get relY and relX positions
75
+ */
76
+ var relY = self.getRelY($wrapper, event);
77
+ var relX = self.getRelX($wrapper, event);
78
+
79
+
80
+ /**
81
+ * If relY and/or relX are false, return the event
82
+ */
83
+ if (!relY && !relX) {
84
+ return;
85
+ }
86
+
87
+
88
+ /**
89
+ * Get the ripple color
90
+ */
91
+ var rippleColor = self.getRipplesColor($element);
92
+
93
+
94
+ /**
95
+ * Create the ripple element
96
+ */
97
+ var $ripple = $("<div></div>");
98
+
99
+ $ripple
100
+ .addClass("ripple")
101
+ .css({
102
+ "left": relX,
103
+ "top": relY,
104
+ "background-color": rippleColor
105
+ });
106
+
107
+
108
+ /**
109
+ * Append the ripple to the wrapper
110
+ */
111
+ $wrapper.append($ripple);
112
+
113
+
114
+ /**
115
+ * Make sure the ripple has the styles applied (ugly hack but it works)
116
+ */
117
+ (function() {
118
+ return window.getComputedStyle($ripple[0]).opacity; })();
119
+
120
+
121
+ /**
122
+ * Turn on the ripple animation
123
+ */
124
+ self.rippleOn($element, $ripple);
125
+
126
+
127
+ /**
128
+ * Call the rippleEnd function when the transition "on" ends
129
+ */
130
+ setTimeout(function() {
131
+ self.rippleEnd($ripple);
132
+ }, 500);
133
+
134
+
135
+ /**
136
+ * Detect when the user leaves the element
137
+ */
138
+ $element.on("mouseup mouseleave touchend", function() {
139
+ $ripple.data("mousedown", "off");
140
+
141
+ if ($ripple.data("animating") === "off") {
142
+ self.rippleOut($ripple);
143
+ }
144
+ });
145
+
146
+ });
147
+ };
148
+
149
+
150
+ /**
151
+ * Get the new size based on the element height/width and the ripple width
152
+ */
153
+ Ripples.prototype.getNewSize = function($element, $ripple) {
154
+
155
+ return (Math.max($element.outerWidth(), $element.outerHeight()) / $ripple.outerWidth()) * 2.5;
156
+ };
157
+
158
+
159
+ /**
160
+ * Get the relX
161
+ */
162
+ Ripples.prototype.getRelX = function($wrapper, event) {
163
+ var wrapperOffset = $wrapper.offset();
164
+
165
+ if (!self.isTouch()) {
166
+ /**
167
+ * Get the mouse position relative to the ripple wrapper
168
+ */
169
+ return event.pageX - wrapperOffset.left;
170
+ } else {
171
+ /**
172
+ * Make sure the user is using only one finger and then get the touch
173
+ * position relative to the ripple wrapper
174
+ */
175
+ event = event.originalEvent;
176
+
177
+ if (event.touches.length === 1) {
178
+ return event.touches[0].pageX - wrapperOffset.left;
179
+ }
180
+
181
+ return false;
182
+ }
183
+ };
184
+
185
+
186
+ /**
187
+ * Get the relY
188
+ */
189
+ Ripples.prototype.getRelY = function($wrapper, event) {
190
+ var wrapperOffset = $wrapper.offset();
191
+
192
+ if (!self.isTouch()) {
193
+ /**
194
+ * Get the mouse position relative to the ripple wrapper
195
+ */
196
+ return event.pageY - wrapperOffset.top;
197
+ } else {
198
+ /**
199
+ * Make sure the user is using only one finger and then get the touch
200
+ * position relative to the ripple wrapper
201
+ */
202
+ event = event.originalEvent;
203
+
204
+ if (event.touches.length === 1) {
205
+ return event.touches[0].pageY - wrapperOffset.top;
206
+ }
207
+
208
+ return false;
209
+ }
210
+ };
211
+
212
+
213
+ /**
214
+ * Get the ripple color
215
+ */
216
+ Ripples.prototype.getRipplesColor = function($element) {
217
+
218
+ var color = $element.data("ripple-color") ? $element.data("ripple-color") : window.getComputedStyle($element[0]).color;
219
+
220
+ return color;
221
+ };
222
+
223
+
224
+ /**
225
+ * Verify if the client browser has transistion support
226
+ */
227
+ Ripples.prototype.hasTransitionSupport = function() {
228
+ var thisBody = document.body || document.documentElement;
229
+ var thisStyle = thisBody.style;
230
+
231
+ var support = (
232
+ thisStyle.transition !== undefined ||
233
+ thisStyle.WebkitTransition !== undefined ||
234
+ thisStyle.MozTransition !== undefined ||
235
+ thisStyle.MsTransition !== undefined ||
236
+ thisStyle.OTransition !== undefined
237
+ );
238
+
239
+ return support;
240
+ };
241
+
242
+
243
+ /**
244
+ * Verify if the client is using a mobile device
245
+ */
246
+ Ripples.prototype.isTouch = function() {
247
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
248
+ };
249
+
250
+
251
+ /**
252
+ * End the animation of the ripple
253
+ */
254
+ Ripples.prototype.rippleEnd = function($ripple) {
255
+ $ripple.data("animating", "off");
256
+
257
+ if ($ripple.data("mousedown") === "off") {
258
+ self.rippleOut($ripple);
259
+ }
260
+ };
261
+
262
+
263
+ /**
264
+ * Turn off the ripple effect
265
+ */
266
+ Ripples.prototype.rippleOut = function($ripple) {
267
+ $ripple.off();
268
+
269
+ if (self.hasTransitionSupport()) {
270
+ $ripple.addClass("ripple-out");
271
+ } else {
272
+ $ripple.animate({ "opacity": 0 }, 100, function() {
273
+ $ripple.trigger("transitionend");
274
+ });
275
+ }
276
+
277
+ $ripple.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function() {
278
+ $ripple.remove();
279
+ });
280
+ };
281
+
282
+
283
+ /**
284
+ * Turn on the ripple effect
285
+ */
286
+ Ripples.prototype.rippleOn = function($element, $ripple) {
287
+ var size = self.getNewSize($element, $ripple);
288
+
289
+ if (self.hasTransitionSupport()) {
290
+ $ripple
291
+ .css({
292
+ "-ms-transform": "scale(" + size + ")",
293
+ "-moz-transform": "scale(" + size + ")",
294
+ "-webkit-transform": "scale(" + size + ")",
295
+ "transform": "scale(" + size + ")"
296
+ })
297
+ .addClass("ripple-on")
298
+ .data("animating", "on")
299
+ .data("mousedown", "on");
300
+ } else {
301
+ $ripple.animate({
302
+ "width": Math.max($element.outerWidth(), $element.outerHeight()) * 2,
303
+ "height": Math.max($element.outerWidth(), $element.outerHeight()) * 2,
304
+ "margin-left": Math.max($element.outerWidth(), $element.outerHeight()) * (-1),
305
+ "margin-top": Math.max($element.outerWidth(), $element.outerHeight()) * (-1),
306
+ "opacity": 0.2
307
+ }, 500, function() {
308
+ $ripple.trigger("transitionend");
309
+ });
310
+ }
311
+ };
312
+
313
+
314
+ /**
315
+ * Create the jquery plugin function
316
+ */
317
+ $.fn.ripples = function(options) {
318
+ return this.each(function() {
319
+ if (!$.data(this, "plugin_" + ripples)) {
320
+ $.data(this, "plugin_" + ripples, new Ripples(this, options));
321
+ }
322
+ });
323
+ };
324
+
325
+ })(jQuery, window, document);