diff --git a/Gruntfile.js b/Gruntfile.js
index b4fe75dd..9b5d86f6 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -52,10 +52,13 @@ module.exports = function(grunt) {
},
uglify: {
+ options: {
+ sourceMap: true
+ },
minifyjs: {
files: {
- "dist/js/material.min.js": "scripts/material.js",
- "dist/js/ripples.min.js": "scripts/ripples.js"
+ "dist/js/material.min.js": "dist/js/material.js",
+ "dist/js/ripples.min.js": "dist/js/ripples.js"
}
}
},
@@ -164,9 +167,9 @@ module.exports = function(grunt) {
});
- grunt.registerTask("default", ["less", "autoprefixer", "cssmin", "uglify", "copy"]);
+ grunt.registerTask("default", ["less", "autoprefixer", "cssmin", "copy", "uglify"]);
- grunt.registerTask("scss", ["sass", "autoprefixer", "cssmin", "uglify", "copy"]);
+ grunt.registerTask("scss", ["sass", "autoprefixer", "cssmin", "copy", "uglify"]);
grunt.registerTask("build", function(target) {
var buildType = "default";
diff --git a/dist/css/ripples.css b/dist/css/ripples.css
index f6595fac..b9cbc21e 100644
--- a/dist/css/ripples.css
+++ b/dist/css/ripples.css
@@ -19,22 +19,16 @@
margin-top: -10px;
border-radius: 100%;
background-color: rgba(0, 0, 0, 0.05);
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- -webkit-transform-origin: 50%;
- -ms-transform-origin: 50%;
- transform-origin: 50%;
+ transform: scale(1);
+ transform-origin: 50%;
opacity: 0;
pointer-events: none;
}
.ripple.ripple-on {
- -webkit-transition: opacity 0.15s ease-in 0s, -webkit-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
- transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
- opacity: 1;
+ transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
+ opacity: 0.2;
}
.ripple.ripple-out {
- -webkit-transition: opacity 0.1s linear 0s !important;
- transition: opacity 0.1s linear 0s !important;
+ transition: opacity 0.1s linear 0s !important;
opacity: 0;
}
diff --git a/dist/css/ripples.min.css b/dist/css/ripples.min.css
index c53a3d61..62e46469 100644
--- a/dist/css/ripples.min.css
+++ b/dist/css/ripples.min.css
@@ -1 +1 @@
-.withripple{position:relative}.ripple-wrapper{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;overflow:hidden;border-radius:inherit}.ripple{position:absolute;width:20px;height:20px;margin-left:-10px;margin-top:-10px;border-radius:100%;background-color:rgba(0,0,0,.05);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-webkit-transform-origin:50%;-ms-transform-origin:50%;transform-origin:50%;opacity:0;pointer-events:none}.ripple.ripple-on{-webkit-transition:opacity .15s ease-in 0s,-webkit-transform .5s cubic-bezier(0.4,0,.2,1) .1s;transition:opacity .15s ease-in 0s,transform .5s cubic-bezier(0.4,0,.2,1) .1s;opacity:1}.ripple.ripple-out{-webkit-transition:opacity .1s linear 0s!important;transition:opacity .1s linear 0s!important;opacity:0}
+.withripple{position:relative}.ripple-wrapper{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;overflow:hidden;border-radius:inherit}.ripple{position:absolute;width:20px;height:20px;margin-left:-10px;margin-top:-10px;border-radius:100%;background-color:rgba(0,0,0,.05);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-webkit-transform-origin:50%;-ms-transform-origin:50%;transform-origin:50%;opacity:0;pointer-events:none}.ripple.ripple-on{-webkit-transition:opacity .15s ease-in 0s,-webkit-transform .5s cubic-bezier(0.4,0,.2,1) .1s;transition:opacity .15s ease-in 0s,transform .5s cubic-bezier(0.4,0,.2,1) .1s;opacity:.2}.ripple.ripple-out{-webkit-transition:opacity .1s linear 0s!important;transition:opacity .1s linear 0s!important;opacity:0}
diff --git a/dist/js/material.js b/dist/js/material.js
index 6cb3804b..4706667e 100644
--- a/dist/js/material.js
+++ b/dist/js/material.js
@@ -1,159 +1,170 @@
-/* globals jQuery, ripples */
+/* globals jQuery */
(function($) {
- // Selector to select only not already processed elements
- $.expr[":"].notmdproc = function(obj){
- if ($(obj).data("mdproc")) {
- return false;
- } else {
- return true;
- }
- };
-
- function _isChar(evt) {
- if (typeof evt.which == "undefined") {
- return true;
- } else if (typeof evt.which == "number" && evt.which > 0) {
- return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
- }
- return false;
+ // Selector to select only not already processed elements
+ $.expr[":"].notmdproc = function(obj){
+ if ($(obj).data("mdproc")) {
+ return false;
+ } else {
+ return true;
}
+ };
- $.material = {
- "options": {
- "withRipples": [
- ".btn:not(.btn-link)",
- ".card-image",
- ".navbar a:not(.withoutripple)",
- ".dropdown-menu a",
- ".nav-tabs a:not(.withoutripple)",
- ".withripple"
- ].join(","),
- "inputElements": "input.form-control, textarea.form-control, select.form-control",
- "checkboxElements": ".checkbox > label > input[type=checkbox]",
- "radioElements": ".radio > label > input[type=radio]"
- },
- "checkbox": function(selector) {
- // Add fake-checkbox to material checkboxes
- $((selector) ? selector : this.options.checkboxElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .after("");
- },
- "radio": function(selector) {
- // Add fake-radio to material radios
- $((selector) ? selector : this.options.radioElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .after("");
- },
- "input": function(selector) {
- $((selector) ? selector : this.options.inputElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .each( function() {
- var $this = $(this);
- $this.wrap("
");
- $this.after("");
- if ($this.hasClass("floating-label")) {
- var placeholder = $this.attr("placeholder");
- $this.attr("placeholder", null).removeClass("floating-label");
- $this.after("" + placeholder + "
");
- }
- if ($this.val() === null || $this.val() == "undefined" || $this.val() === "") {
- $this.addClass("empty");
- }
- if ($this.parent().next().is("[type=file]")) {
- $this.parent().addClass("fileinput");
- var $input = $this.parent().next().detach();
- $this.after($input);
- }
- });
+ function _isChar(evt) {
+ if (typeof evt.which == "undefined") {
+ return true;
+ } else if (typeof evt.which == "number" && evt.which > 0) {
+ return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
+ }
+ return false;
+ }
- $(document)
- .on("change", ".checkbox input", function() { $(this).blur(); })
- .on("keydown paste", ".form-control", function(e) {
- if(_isChar(e)) {
- $(this).removeClass("empty");
- }
- })
- .on("keyup change", ".form-control", function() {
- var $this = $(this);
- if($this.val() === "") {
- $this.addClass("empty");
- } else {
- $this.removeClass("empty");
- }
- })
- .on("focus", ".form-control-wrapper.fileinput", function() {
- $(this).find("input").addClass("focus");
- })
- .on("blur", ".form-control-wrapper.fileinput", function() {
- $(this).find("input").removeClass("focus");
- })
- .on("change", ".form-control-wrapper.fileinput [type=file]", function() {
- var value = "";
- $.each($(this)[0].files, function(i, file) {
- console.log(file);
- value += file.name + ", ";
- });
- value = value.substring(0, value.length - 2);
- if (value) {
- $(this).prev().removeClass("empty");
- } else {
- $(this).prev().addClass("empty");
- }
- $(this).prev().val(value);
- });
- },
- "ripples": function(selector) {
- ripples.init((selector) ? selector : this.options.withRipples);
- },
- "init": function() {
- this.ripples();
- this.input();
- this.checkbox();
- this.radio();
+ $.material = {
+ "options": {
+ "withRipples": [
+ ".btn:not(.btn-link)",
+ ".card-image",
+ ".navbar a:not(.withoutripple)",
+ ".dropdown-menu a",
+ ".nav-tabs a:not(.withoutripple)",
+ ".withripple"
+ ].join(","),
+ "inputElements": "input.form-control, textarea.form-control, select.form-control",
+ "checkboxElements": ".checkbox > label > input[type=checkbox]",
+ "radioElements": ".radio > label > input[type=radio]"
+ },
+ "checkbox": function(selector) {
+ // Add fake-checkbox to material checkboxes
+ $((selector) ? selector : this.options.checkboxElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("");
+ },
+ "radio": function(selector) {
+ // Add fake-radio to material radios
+ $((selector) ? selector : this.options.radioElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("");
+ },
+ "input": function(selector) {
+ $((selector) ? selector : this.options.inputElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .each( function() {
+ var $this = $(this);
+ $this.wrap("");
+ $this.after("");
- if (document.arrive) {
- document.arrive("input, textarea, select", function() {
- $.material.init();
- });
- }
-
- // Detect autofill
- (function() {
- // This part of code will detect autofill when the page is loading (username and password inputs for example)
- var loading = setInterval(function() {
- $("input").each(function() {
- if ($(this).val() !== $(this).attr("value")) {
- $(this).trigger("change");
- }
- });
- }, 100);
- // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
- setTimeout(function() {
- clearInterval(loading);
- }, 10000);
- // Now we just listen on inputs of the focused form (because user can select from the autofill dropdown only when the input has focus)
- var focused;
- $(document)
- .on("focus", "input", function() {
- var $inputs = $(this).parents("form").find("input");
- focused = setInterval(function() {
- $inputs.each(function() {
- if ($(this).val() !== $(this).attr("value")) {
- $(this).trigger("change");
- }
- });
- }, 100);
- })
- .on("blur", "input", function() {
- clearInterval(focused);
- });
-
- })();
+ // Add floating label if required
+ if ($this.hasClass("floating-label")) {
+ var placeholder = $this.attr("placeholder");
+ $this.attr("placeholder", null).removeClass("floating-label");
+ $this.after("" + placeholder + "
");
}
- };
+
+ // Add hint label if required
+ if ($this.attr("data-hint")) {
+ $this.after("" + $this.attr("data-hint") + "
");
+ }
+
+ // Set as empty if is empty (damn I must improve this...)
+ if ($this.val() === null || $this.val() == "undefined" || $this.val() === "") {
+ $this.addClass("empty");
+ }
+
+ // Support for file input
+ if ($this.parent().next().is("[type=file]")) {
+ $this.parent().addClass("fileinput");
+ var $input = $this.parent().next().detach();
+ $this.after($input);
+ }
+ });
+
+ $(document)
+ .on("change", ".checkbox input[type=checkbox]", function() { $(this).blur(); })
+ .on("keydown paste", ".form-control", function(e) {
+ if(_isChar(e)) {
+ $(this).removeClass("empty");
+ }
+ })
+ .on("keyup change", ".form-control", function() {
+ var $this = $(this);
+ if($this.val() === "") {
+ $this.addClass("empty");
+ } else {
+ $this.removeClass("empty");
+ }
+ })
+ .on("focus", ".form-control-wrapper.fileinput", function() {
+ $(this).find("input").addClass("focus");
+ })
+ .on("blur", ".form-control-wrapper.fileinput", function() {
+ $(this).find("input").removeClass("focus");
+ })
+ .on("change", ".form-control-wrapper.fileinput [type=file]", function() {
+ var value = "";
+ $.each($(this)[0].files, function(i, file) {
+ console.log(file);
+ value += file.name + ", ";
+ });
+ value = value.substring(0, value.length - 2);
+ if (value) {
+ $(this).prev().removeClass("empty");
+ } else {
+ $(this).prev().addClass("empty");
+ }
+ $(this).prev().val(value);
+ });
+ },
+ "ripples": function(selector) {
+ $.ripples({"target": (selector) ? selector : this.options.withRipples});
+ },
+ "init": function() {
+ this.ripples();
+ this.input();
+ this.checkbox();
+ this.radio();
+
+ if (document.arrive) {
+ document.arrive("input, textarea, select", function() {
+ $.material.init();
+ });
+ }
+
+ // Detect autofill
+ (function() {
+ // This part of code will detect autofill when the page is loading (username and password inputs for example)
+ var loading = setInterval(function() {
+ $("input[type!=checkbox]").each(function() {
+ if ($(this).val() && $(this).val() !== $(this).attr("value")) {
+ $(this).trigger("change");
+ }
+ });
+ }, 100);
+ // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
+ setTimeout(function() {
+ clearInterval(loading);
+ }, 10000);
+ // Now we just listen on inputs of the focused form (because user can select from the autofill dropdown only when the input has focus)
+ var focused;
+ $(document)
+ .on("focus", "input", function() {
+ var $inputs = $(this).parents("form").find("input");
+ focused = setInterval(function() {
+ $inputs.each(function() {
+ if ($(this).val() !== $(this).attr("value")) {
+ $(this).trigger("change");
+ }
+ });
+ }, 100);
+ })
+ .on("blur", "input", function() {
+ clearInterval(focused);
+ });
+
+ })();
+ }
+ };
})(jQuery);
diff --git a/dist/js/material.min.js b/dist/js/material.min.js
index 6d9bb49e..2055294a 100644
--- a/dist/js/material.min.js
+++ b/dist/js/material.min.js
@@ -1 +1,2 @@
-!function(a){function b(a){return"undefined"==typeof a.which?!0:"number"==typeof a.which&&a.which>0?!a.ctrlKey&&!a.metaKey&&!a.altKey&&8!=a.which:!1}a.expr[":"].notmdproc=function(b){return a(b).data("mdproc")?!1:!0},a.material={options:{withRipples:[".btn:not(.btn-link)",".card-image",".navbar a:not(.withoutripple)",".dropdown-menu a",".nav-tabs a:not(.withoutripple)",".withripple"].join(","),inputElements:"input.form-control, textarea.form-control, select.form-control",checkboxElements:".checkbox > label > input[type=checkbox]",radioElements:".radio > label > input[type=radio]"},checkbox:function(b){a(b?b:this.options.checkboxElements).filter(":notmdproc").data("mdproc",!0).after("")},radio:function(b){a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("")},input:function(c){a(c?c:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this);if(b.wrap(""),b.after(""),b.hasClass("floating-label")){var c=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label"),b.after(""+c+"
")}if(b.attr("data-hint")&&b.after(""+b.attr("data-hint")+"
"),(null===b.val()||"undefined"==b.val()||""===b.val())&&b.addClass("empty"),b.parent().next().is("[type=file]")){b.parent().addClass("fileinput");var d=b.parent().next().detach();b.after(d)}}),a(document).on("change",".checkbox input[type=checkbox]",function(){a(this).blur()}).on("keydown paste",".form-control",function(c){b(c)&&a(this).removeClass("empty")}).on("keyup change",".form-control",function(){var b=a(this);""===b.val()?b.addClass("empty"):b.removeClass("empty")}).on("focus",".form-control-wrapper.fileinput",function(){a(this).find("input").addClass("focus")}).on("blur",".form-control-wrapper.fileinput",function(){a(this).find("input").removeClass("focus")}).on("change",".form-control-wrapper.fileinput [type=file]",function(){var b="";a.each(a(this)[0].files,function(a,c){console.log(c),b+=c.name+", "}),b=b.substring(0,b.length-2),b?a(this).prev().removeClass("empty"):a(this).prev().addClass("empty"),a(this).prev().val(b)})},ripples:function(a){ripples.init(a?a:this.options.withRipples)},init:function(){this.ripples(),this.input(),this.checkbox(),this.radio(),document.arrive&&document.arrive("input, textarea, select",function(){a.material.init()}),function(){var b=setInterval(function(){a("input[type!=checkbox]").each(function(){a(this).val()&&a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100);setTimeout(function(){clearInterval(b)},1e4);var c;a(document).on("focus","input",function(){var b=a(this).parents("form").find("input");c=setInterval(function(){b.each(function(){a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100)}).on("blur","input",function(){clearInterval(c)})}()}}}(jQuery);
+!function(a){function b(a){return"undefined"==typeof a.which?!0:"number"==typeof a.which&&a.which>0?!a.ctrlKey&&!a.metaKey&&!a.altKey&&8!=a.which:!1}a.expr[":"].notmdproc=function(b){return a(b).data("mdproc")?!1:!0},a.material={options:{withRipples:[".btn:not(.btn-link)",".card-image",".navbar a:not(.withoutripple)",".dropdown-menu a",".nav-tabs a:not(.withoutripple)",".withripple"].join(","),inputElements:"input.form-control, textarea.form-control, select.form-control",checkboxElements:".checkbox > label > input[type=checkbox]",radioElements:".radio > label > input[type=radio]"},checkbox:function(b){a(b?b:this.options.checkboxElements).filter(":notmdproc").data("mdproc",!0).after("")},radio:function(b){a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("")},input:function(c){a(c?c:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this);if(b.wrap(""),b.after(""),b.hasClass("floating-label")){var c=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label"),b.after(""+c+"
")}if(b.attr("data-hint")&&b.after(""+b.attr("data-hint")+"
"),(null===b.val()||"undefined"==b.val()||""===b.val())&&b.addClass("empty"),b.parent().next().is("[type=file]")){b.parent().addClass("fileinput");var d=b.parent().next().detach();b.after(d)}}),a(document).on("change",".checkbox input[type=checkbox]",function(){a(this).blur()}).on("keydown paste",".form-control",function(c){b(c)&&a(this).removeClass("empty")}).on("keyup change",".form-control",function(){var b=a(this);""===b.val()?b.addClass("empty"):b.removeClass("empty")}).on("focus",".form-control-wrapper.fileinput",function(){a(this).find("input").addClass("focus")}).on("blur",".form-control-wrapper.fileinput",function(){a(this).find("input").removeClass("focus")}).on("change",".form-control-wrapper.fileinput [type=file]",function(){var b="";a.each(a(this)[0].files,function(a,c){console.log(c),b+=c.name+", "}),b=b.substring(0,b.length-2),b?a(this).prev().removeClass("empty"):a(this).prev().addClass("empty"),a(this).prev().val(b)})},ripples:function(b){a.ripples({target:b?b:this.options.withRipples})},init:function(){this.ripples(),this.input(),this.checkbox(),this.radio(),document.arrive&&document.arrive("input, textarea, select",function(){a.material.init()}),function(){var b=setInterval(function(){a("input[type!=checkbox]").each(function(){a(this).val()&&a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100);setTimeout(function(){clearInterval(b)},1e4);var c;a(document).on("focus","input",function(){var b=a(this).parents("form").find("input");c=setInterval(function(){b.each(function(){a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100)}).on("blur","input",function(){clearInterval(c)})}()}}}(jQuery);
+//# sourceMappingURL=material.min.js.map
diff --git a/dist/js/material.min.js.map b/dist/js/material.min.js.map
new file mode 100644
index 00000000..efb628fd
--- /dev/null
+++ b/dist/js/material.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"material.min.js","sources":["material.js"],"names":["$","_isChar","evt","which","ctrlKey","metaKey","altKey","expr","notmdproc","obj","data","material","options","withRipples","join","inputElements","checkboxElements","radioElements","checkbox","selector","this","filter","after","radio","input","each","$this","wrap","hasClass","placeholder","attr","removeClass","val","addClass","parent","next","is","$input","detach","document","on","blur","e","find","value","files","i","file","console","log","name","substring","length","prev","ripples","target","init","arrive","loading","setInterval","trigger","setTimeout","clearInterval","focused","$inputs","parents","jQuery"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/js/ripples.js b/dist/js/ripples.js
index 0f10784b..399c4fdf 100644
--- a/dist/js/ripples.js
+++ b/dist/js/ripples.js
@@ -1,189 +1,105 @@
/* Copyright 2014+, Federico Zivolo, LICENSE at https://github.com/FezVrasta/bootstrap-material-design/blob/master/LICENSE.md */
-/* globals CustomEvent */
-window.ripples = {
- done: false,
- init : function(withRipple) {
- "use strict";
+/* globals jQuery */
- if (this.done) {
- return console.log("Ripples.js was already initialzied.");
- }
+(function($) {
+ $.ripples = function(options) {
- this.done = true;
+ // Default options
+ var defaultOptions = {
+ "target": ".btn:not(.btn-link), .card-image, .navbar a:not(.withoutripple), .nav-tabs a:not(.withoutripple), .withripple"
+ };
- // Cross browser matches function
- function matchesSelector(domElement, selector) {
- var matches = domElement.matches ||
- domElement.matchesSelector ||
- domElement.webkitMatchesSelector ||
- domElement.mozMatchesSelector ||
- domElement.msMatchesSelector ||
- domElement.oMatchesSelector;
- return matches.call(domElement, selector);
- }
+ // Fade out the ripple and then destroy it
+ function rippleOut(ripple) {
- // animations time
- var rippleOutTime = 100,
- rippleStartTime = 500;
+ // Unbind events from ripple
+ ripple.off();
- // Helper to bind events on dynamically created elements
- var bind = function(events, selector, callback) {
- if (typeof events === "string") {
- events = [events];
- }
- events.forEach(function(event) {
- document.addEventListener(event, function(e) {
- var target = (typeof e.detail !== "number") ? e.detail : e.target;
+ // Start the out animation
+ ripple.addClass("ripple-out");
- if (matchesSelector(target, selector)) {
- callback(e, target);
- }
- });
- });
- };
-
- var rippleStart = function(e, target, callback) {
-
- // Init variables
- var $rippleWrapper = target,
- $el = $rippleWrapper.parentNode,
- $ripple = document.createElement("div"),
- elPos = $el.getBoundingClientRect(),
- // Mouse pos in most cases
- mousePos = {x: e.clientX - elPos.left, y: ((window.ontouchstart) ? e.clientY - window.scrollY: e.clientY) - elPos.top},
- scale = "scale(" + Math.round($rippleWrapper.offsetWidth / 5) + ")",
- rippleEnd = new CustomEvent("rippleEnd", {detail: $ripple}),
- _rippleOpacity = 0.3,
- refreshElementStyle;
-
-
- // If multitouch is detected or some other black magic suff is happening...
- if (e.touches) {
- mousePos = {x: e.touches[0].clientX - elPos.left, y: e.touches[0].clientY - elPos.top};
- }
-
- $ripplecache = $ripple;
-
- // Set ripple class
- $ripple.className = "ripple";
-
- // Move ripple to the mouse position
- $ripple.setAttribute("style", "left:" + mousePos.x + "px; top:" + mousePos.y + "px;");
-
- // Get the clicked target's text color, this will be applied to the ripple as background-color.
- var targetColor = window.getComputedStyle($el).color;
-
- // Convert the rgb color to an rgba color with opacity set to __rippleOpacity__
- if ( targetColor.indexOf("rgba") >= 0 ) {
- var alphaPosition = targetColor.lastIndexOf(",") + 1;
- targetColor = targetColor.substring(0, alphaPosition) + _rippleOpacity + ")";
- } else {
- targetColor = targetColor.replace("rgb", "rgba").replace(")", ", " + _rippleOpacity + ")");
- }
-
- // Insert new ripple into ripple wrapper
- $rippleWrapper.appendChild($ripple);
-
- // Make sure the ripple has the class applied (ugly hack but it works)
- refreshElementStyle = window.getComputedStyle($ripple).opacity;
-
- // Let other funtions know that this element is animating
- $ripple.dataset.animating = 1;
-
- // Set scale value, background-color and opacity to ripple and animate it
- $ripple.className = "ripple ripple-on";
-
- // Prepare the style of the ripple
- var rippleStyle = [
- $ripple.getAttribute("style"),
- "background-color: " + targetColor,
- "-ms-transform: " + scale,
- "-moz-transform:" + scale,
- "-webkit-transform:" + scale,
- "transform: " + scale
- ];
-
- // Apply the style
- $ripple.setAttribute("style", rippleStyle.join(";"));
-
- // This function is called when the animation is finished
- setTimeout(function() {
-
- // Let know to other functions that this element has finished the animation
- $ripple.dataset.animating = 0;
- document.dispatchEvent(rippleEnd);
- if (callback) {
- callback();
- }
-
- }, rippleStartTime);
-
- };
-
- var rippleOut = function($ripple) {
- // Clear previous animation
- $ripple.className = "ripple ripple-on ripple-out";
-
- // Let ripple fade out (with CSS)
- setTimeout(function() {
- $ripple.remove();
- }, rippleOutTime);
- };
-
- // Helper, need to know if mouse is up or down
- var mouseDown = false;
- bind(["mousedown", "touchstart"], "*", function() {
- mouseDown = true;
- });
- bind(["mouseup", "touchend", "mouseout"], "*", function() {
- mouseDown = false;
- });
-
- // Append ripple wrapper if not exists already
- var rippleInit = function(e, target) {
- if (target.getElementsByClassName("ripple-wrapper").length === 0) {
- target.className += " withripple";
- var $rippleWrapper = document.createElement("div");
- $rippleWrapper.className = "ripple-wrapper";
- target.appendChild($rippleWrapper);
- }
- };
-
- var $ripplecache;
-
- // Events handler
- // init RippleJS and start ripple effect on mousedown
- bind(["mouseover"], withRipple, rippleInit);
-
- // Init if the device is touch screen
- bind(["touchstart"], withRipple, rippleInit);
-
- // start ripple effect on mousedown
- bind(["mousedown", "touchstart"], ".ripple-wrapper", function(e, $ripple) {
- // Start ripple only on left or middle mouse click and touch click
- if (e.which === 0 || e.which === 1 || e.which === 2) {
- rippleStart(e, $ripple);
- }
- });
-
- // if animation ends and user is not holding mouse then destroy the ripple
- bind("rippleEnd", ".ripple-wrapper .ripple", function(e, $ripple) {
-
- var $ripples = $ripple.parentNode.getElementsByClassName("ripple");
-
- if (!mouseDown || ( $ripples[0] == $ripple && $ripples.length > 1)) {
- rippleOut($ripple);
- }
- });
-
- // Destroy ripple when mouse is not holded anymore if the ripple still exists
- bind(["mouseup", "touchend", "mouseout"], ".ripple-wrapper", function() {
- var $ripple = $ripplecache;
- if ($ripple && $ripple.dataset.animating != 1) {
- rippleOut($ripple);
- }
- });
+ // This function is called when the transition "out" ends
+ ripple.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
+ ripple.remove();
+ });
}
-};
+
+ // Apply custom options
+ options = $.extend(defaultOptions, options);
+
+
+ $(document)
+ .on("mousedown", options.target, function(e) {
+ // If the ripple wrapper does not exists, create it
+ if (!$(this).find(".ripple-wrapper").length) {
+ $(this).append("");
+ }
+
+ var wrapper = $(this).find(".ripple-wrapper");
+
+ // Get the mouse position relative to the ripple wrapper
+ var wrapperOffset = wrapper.offset();
+ var relX = e.pageX - wrapperOffset.left;
+ var relY = e.pageY - wrapperOffset.top;
+
+ // Meet the new ripple
+ var ripple = $("");
+
+ // Add to it the ripple class
+ ripple.addClass("ripple");
+
+ // Position it in the right place
+ ripple.css({"left": relX, "top": relY});
+
+ // Set the background color of the ripple
+ ripple.css({"background-color": window.getComputedStyle($(this)[0]).color});
+
+ // Spawn it
+ wrapper.append(ripple);
+
+ // Make sure the ripple has the styles applied (ugly hack but it works)
+ (function() { return window.getComputedStyle(ripple[0]).opacity; })();
+
+ // Set the new size
+ var size = (Math.max($(this).outerWidth(), $(this).outerHeight()) / ripple.outerWidth()) * 2.5;
+
+ ripple.css({
+ "-ms-transform": "scale(" + size + ")",
+ "-moz-transform": "scale(" + size + ")",
+ "-webkit-transform": "scale(" + size + ")",
+ "transform": "scale(" + size + ")"
+ });
+
+ // Start the transition
+ ripple.addClass("ripple-on");
+ ripple.data("animating", "on");
+ ripple.data("mousedown", "on");
+
+ // This function is called when the transition "on" ends
+ setTimeout(function() {
+ ripple.data("animating", "off");
+ if (ripple.data("mousedown") == "off") {
+ rippleOut(ripple);
+ }
+ }, 500);
+
+ // On mouseup or on mouseleave, set the mousedown flag to "off" and try to destroy the ripple
+ wrapper.on("mouseup mouseleave", function() {
+ ripple.data("mousedown", "off");
+ // If the transition "on" is finished then we can destroy the ripple with transition "out"
+ if (ripple.data("animating") == "off") {
+ rippleOut(ripple);
+ }
+ });
+
+ });
+
+ };
+
+ $.fn.ripples = function() {
+ $.ripples({"target": $(this)});
+ };
+
+})(jQuery);
diff --git a/dist/js/ripples.min.js b/dist/js/ripples.min.js
index fa37eb6d..d057eccd 100644
--- a/dist/js/ripples.min.js
+++ b/dist/js/ripples.min.js
@@ -1 +1,2 @@
-window.ripples={done:!1,init:function(a){"use strict";function b(a,b){var c=a.matches||a.matchesSelector||a.webkitMatchesSelector||a.mozMatchesSelector||a.msMatchesSelector||a.oMatchesSelector;return c.call(a,b)}if(this.done)return console.log("Ripples.js was already initialzied.");this.done=!0;var c=100,d=500,e=function(a,c,d){"string"==typeof a&&(a=[a]),a.forEach(function(a){document.addEventListener(a,function(a){var e="number"!=typeof a.detail?a.detail:a.target;b(e,c)&&d(a,e)})})},f=function(a,b,c){var e,f=b,g=f.parentNode,h=document.createElement("div"),j=g.getBoundingClientRect(),k={x:a.clientX-j.left,y:(window.ontouchstart?a.clientY-window.scrollY:a.clientY)-j.top},l="scale("+Math.round(f.offsetWidth/5)+")",m=new CustomEvent("rippleEnd",{detail:h}),n=.3;a.touches&&(k={x:a.touches[0].clientX-j.left,y:a.touches[0].clientY-j.top}),i=h,h.className="ripple",h.setAttribute("style","left:"+k.x+"px; top:"+k.y+"px;");var o=window.getComputedStyle(g).color;if(o.indexOf("rgba")>=0){var p=o.lastIndexOf(",")+1;o=o.substring(0,p)+n+")"}else o=o.replace("rgb","rgba").replace(")",", "+n+")");f.appendChild(h),e=window.getComputedStyle(h).opacity,h.dataset.animating=1,h.className="ripple ripple-on";var q=[h.getAttribute("style"),"background-color: "+o,"-ms-transform: "+l,"-moz-transform:"+l,"-webkit-transform:"+l,"transform: "+l];h.setAttribute("style",q.join(";")),setTimeout(function(){h.dataset.animating=0,document.dispatchEvent(m),c&&c()},d)},g=function(a){a.className="ripple ripple-on ripple-out",setTimeout(function(){a.remove()},c)},h=!1;e(["mousedown","touchstart"],"*",function(){h=!0}),e(["mouseup","touchend","mouseout"],"*",function(){h=!1});var i,j=function(a,b){if(0===b.getElementsByClassName("ripple-wrapper").length){b.className+=" withripple";var c=document.createElement("div");c.className="ripple-wrapper",b.appendChild(c)}};e(["mouseover"],a,j),e(["touchstart"],a,j),e(["mousedown","touchstart"],".ripple-wrapper",function(a,b){(0===a.which||1===a.which||2===a.which)&&f(a,b)}),e("rippleEnd",".ripple-wrapper .ripple",function(a,b){var c=b.parentNode.getElementsByClassName("ripple");(!h||c[0]==b&&c.length>1)&&g(b)}),e(["mouseup","touchend","mouseout"],".ripple-wrapper",function(){var a=i;a&&1!=a.dataset.animating&&g(a)})}};
+!function(a){a.ripples=function(b){function c(a){a.off(),a.addClass("ripple-out"),a.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){a.remove()})}var d={target:".btn:not(.btn-link), .card-image, .navbar a:not(.withoutripple), .nav-tabs a:not(.withoutripple), .withripple"};b=a.extend(d,b),a(document).on("mousedown",b.target,function(b){a(this).find(".ripple-wrapper").length||a(this).append("");var d=a(this).find(".ripple-wrapper"),e=d.offset(),f=b.pageX-e.left,g=b.pageY-e.top,h=a("");h.addClass("ripple"),h.css({left:f,top:g}),h.css({"background-color":window.getComputedStyle(a(this)[0]).color}),d.append(h),function(){return window.getComputedStyle(h[0]).opacity}();var i=Math.max(a(this).outerWidth(),a(this).outerHeight())/h.outerWidth()*2.5;h.css({"-ms-transform":"scale("+i+")","-moz-transform":"scale("+i+")","-webkit-transform":"scale("+i+")",transform:"scale("+i+")"}),h.addClass("ripple-on"),h.data("animating","on"),h.data("mousedown","on"),setTimeout(function(){h.data("animating","off"),"off"==h.data("mousedown")&&c(h)},500),d.on("mouseup mouseleave",function(){h.data("mousedown","off"),"off"==h.data("animating")&&c(h)})})},a.fn.ripples=function(){a.ripples({target:a(this)})}}(jQuery);
+//# sourceMappingURL=ripples.min.js.map
diff --git a/dist/js/ripples.min.js.map b/dist/js/ripples.min.js.map
new file mode 100644
index 00000000..34744f62
--- /dev/null
+++ b/dist/js/ripples.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"ripples.min.js","sources":["ripples.js"],"names":["$","ripples","options","rippleOut","ripple","off","addClass","on","remove","defaultOptions","target","extend","document","e","this","find","length","append","wrapper","wrapperOffset","offset","relX","pageX","left","relY","pageY","top","css","background-color","window","getComputedStyle","color","opacity","size","Math","max","outerWidth","outerHeight","-ms-transform","-moz-transform","-webkit-transform","transform","data","setTimeout","fn","jQuery"],"mappings":"CAGA,SAAUA,GACRA,EAAEC,QAAU,SAASC,GASnB,QAASC,GAAUC,GAGjBA,EAAOC,MAGPD,EAAOE,SAAS,cAGhBF,EAAOG,GAAG,mEAAoE,WAC5EH,EAAOI,WAhBX,GAAIC,IACFC,OAAU,gHAqBZR,GAAUF,EAAEW,OAAOF,EAAgBP,GAGnCF,EAAEY,UACDL,GAAG,YAAaL,EAAQQ,OAAQ,SAASG,GAEnCb,EAAEc,MAAMC,KAAK,mBAAmBC,QACnChB,EAAEc,MAAMG,OAAO,mCAGjB,IAAIC,GAAUlB,EAAEc,MAAMC,KAAK,mBAGvBI,EAAgBD,EAAQE,SACxBC,EAAOR,EAAES,MAAQH,EAAcI,KAC/BC,EAAOX,EAAEY,MAAQN,EAAcO,IAG/BtB,EAASJ,EAAE,cAGfI,GAAOE,SAAS,UAGhBF,EAAOuB,KAAKJ,KAAQF,EAAMK,IAAOF,IAGjCpB,EAAOuB,KAAKC,mBAAoBC,OAAOC,iBAAiB9B,EAAEc,MAAM,IAAIiB,QAGpEb,EAAQD,OAAOb,GAGf,WAAc,MAAOyB,QAAOC,iBAAiB1B,EAAO,IAAI4B,UAGxD,IAAIC,GAAQC,KAAKC,IAAInC,EAAEc,MAAMsB,aAAcpC,EAAEc,MAAMuB,eAAiBjC,EAAOgC,aAAgB,GAE3FhC,GAAOuB,KACLW,gBAAiB,SAAWL,EAAO,IACnCM,iBAAkB,SAAWN,EAAO,IACpCO,oBAAqB,SAAWP,EAAO,IACvCQ,UAAa,SAAWR,EAAO,MAIjC7B,EAAOE,SAAS,aAChBF,EAAOsC,KAAK,YAAa,MACzBtC,EAAOsC,KAAK,YAAa,MAGzBC,WAAW,WACTvC,EAAOsC,KAAK,YAAa,OACO,OAA5BtC,EAAOsC,KAAK,cACdvC,EAAUC,IAEX,KAGHc,EAAQX,GAAG,qBAAsB,WAC/BH,EAAOsC,KAAK,YAAa,OAEO,OAA5BtC,EAAOsC,KAAK,cACdvC,EAAUC,QAQlBJ,EAAE4C,GAAG3C,QAAU,WACbD,EAAEC,SAASS,OAAUV,EAAEc,UAGxB+B"}
\ No newline at end of file
diff --git a/less/ripples.less b/less/ripples.less
index 1c3b689f..eb209ec5 100644
--- a/less/ripples.less
+++ b/less/ripples.less
@@ -26,7 +26,7 @@
}
.ripple.ripple-on {
transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
- opacity: 1;
+ opacity: 0.2;
}
.ripple.ripple-out {
transition: opacity 0.1s linear 0s !important;
diff --git a/scripts/material.js b/scripts/material.js
index 30cabe1b..4706667e 100644
--- a/scripts/material.js
+++ b/scripts/material.js
@@ -1,170 +1,170 @@
-/* globals jQuery, ripples */
+/* globals jQuery */
(function($) {
- // Selector to select only not already processed elements
- $.expr[":"].notmdproc = function(obj){
- if ($(obj).data("mdproc")) {
- return false;
- } else {
- return true;
- }
- };
-
- function _isChar(evt) {
- if (typeof evt.which == "undefined") {
- return true;
- } else if (typeof evt.which == "number" && evt.which > 0) {
- return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
- }
- return false;
+ // Selector to select only not already processed elements
+ $.expr[":"].notmdproc = function(obj){
+ if ($(obj).data("mdproc")) {
+ return false;
+ } else {
+ return true;
}
+ };
- $.material = {
- "options": {
- "withRipples": [
- ".btn:not(.btn-link)",
- ".card-image",
- ".navbar a:not(.withoutripple)",
- ".dropdown-menu a",
- ".nav-tabs a:not(.withoutripple)",
- ".withripple"
- ].join(","),
- "inputElements": "input.form-control, textarea.form-control, select.form-control",
- "checkboxElements": ".checkbox > label > input[type=checkbox]",
- "radioElements": ".radio > label > input[type=radio]"
- },
- "checkbox": function(selector) {
- // Add fake-checkbox to material checkboxes
- $((selector) ? selector : this.options.checkboxElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .after("");
- },
- "radio": function(selector) {
- // Add fake-radio to material radios
- $((selector) ? selector : this.options.radioElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .after("");
- },
- "input": function(selector) {
- $((selector) ? selector : this.options.inputElements)
- .filter(":notmdproc")
- .data("mdproc", true)
- .each( function() {
- var $this = $(this);
- $this.wrap("");
- $this.after("");
+ function _isChar(evt) {
+ if (typeof evt.which == "undefined") {
+ return true;
+ } else if (typeof evt.which == "number" && evt.which > 0) {
+ return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
+ }
+ return false;
+ }
- // Add floating label if required
- if ($this.hasClass("floating-label")) {
- var placeholder = $this.attr("placeholder");
- $this.attr("placeholder", null).removeClass("floating-label");
- $this.after("" + placeholder + "
");
- }
+ $.material = {
+ "options": {
+ "withRipples": [
+ ".btn:not(.btn-link)",
+ ".card-image",
+ ".navbar a:not(.withoutripple)",
+ ".dropdown-menu a",
+ ".nav-tabs a:not(.withoutripple)",
+ ".withripple"
+ ].join(","),
+ "inputElements": "input.form-control, textarea.form-control, select.form-control",
+ "checkboxElements": ".checkbox > label > input[type=checkbox]",
+ "radioElements": ".radio > label > input[type=radio]"
+ },
+ "checkbox": function(selector) {
+ // Add fake-checkbox to material checkboxes
+ $((selector) ? selector : this.options.checkboxElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("");
+ },
+ "radio": function(selector) {
+ // Add fake-radio to material radios
+ $((selector) ? selector : this.options.radioElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("");
+ },
+ "input": function(selector) {
+ $((selector) ? selector : this.options.inputElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .each( function() {
+ var $this = $(this);
+ $this.wrap("");
+ $this.after("");
- // Add hint label if required
- if ($this.attr("data-hint")) {
- $this.after("" + $this.attr("data-hint") + "
");
- }
-
- // Set as empty if is empty (damn I must improve this...)
- if ($this.val() === null || $this.val() == "undefined" || $this.val() === "") {
- $this.addClass("empty");
- }
-
- // Support for file input
- if ($this.parent().next().is("[type=file]")) {
- $this.parent().addClass("fileinput");
- var $input = $this.parent().next().detach();
- $this.after($input);
- }
- });
-
- $(document)
- .on("change", ".checkbox input[type=checkbox]", function() { $(this).blur(); })
- .on("keydown paste", ".form-control", function(e) {
- if(_isChar(e)) {
- $(this).removeClass("empty");
- }
- })
- .on("keyup change", ".form-control", function() {
- var $this = $(this);
- if($this.val() === "") {
- $this.addClass("empty");
- } else {
- $this.removeClass("empty");
- }
- })
- .on("focus", ".form-control-wrapper.fileinput", function() {
- $(this).find("input").addClass("focus");
- })
- .on("blur", ".form-control-wrapper.fileinput", function() {
- $(this).find("input").removeClass("focus");
- })
- .on("change", ".form-control-wrapper.fileinput [type=file]", function() {
- var value = "";
- $.each($(this)[0].files, function(i, file) {
- console.log(file);
- value += file.name + ", ";
- });
- value = value.substring(0, value.length - 2);
- if (value) {
- $(this).prev().removeClass("empty");
- } else {
- $(this).prev().addClass("empty");
- }
- $(this).prev().val(value);
- });
- },
- "ripples": function(selector) {
- ripples.init((selector) ? selector : this.options.withRipples);
- },
- "init": function() {
- this.ripples();
- this.input();
- this.checkbox();
- this.radio();
-
- if (document.arrive) {
- document.arrive("input, textarea, select", function() {
- $.material.init();
- });
- }
-
- // Detect autofill
- (function() {
- // This part of code will detect autofill when the page is loading (username and password inputs for example)
- var loading = setInterval(function() {
- $("input[type!=checkbox]").each(function() {
- if ($(this).val() && $(this).val() !== $(this).attr("value")) {
- $(this).trigger("change");
- }
- });
- }, 100);
- // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
- setTimeout(function() {
- clearInterval(loading);
- }, 10000);
- // Now we just listen on inputs of the focused form (because user can select from the autofill dropdown only when the input has focus)
- var focused;
- $(document)
- .on("focus", "input", function() {
- var $inputs = $(this).parents("form").find("input");
- focused = setInterval(function() {
- $inputs.each(function() {
- if ($(this).val() !== $(this).attr("value")) {
- $(this).trigger("change");
- }
- });
- }, 100);
- })
- .on("blur", "input", function() {
- clearInterval(focused);
- });
-
- })();
+ // Add floating label if required
+ if ($this.hasClass("floating-label")) {
+ var placeholder = $this.attr("placeholder");
+ $this.attr("placeholder", null).removeClass("floating-label");
+ $this.after("" + placeholder + "
");
}
- };
+
+ // Add hint label if required
+ if ($this.attr("data-hint")) {
+ $this.after("" + $this.attr("data-hint") + "
");
+ }
+
+ // Set as empty if is empty (damn I must improve this...)
+ if ($this.val() === null || $this.val() == "undefined" || $this.val() === "") {
+ $this.addClass("empty");
+ }
+
+ // Support for file input
+ if ($this.parent().next().is("[type=file]")) {
+ $this.parent().addClass("fileinput");
+ var $input = $this.parent().next().detach();
+ $this.after($input);
+ }
+ });
+
+ $(document)
+ .on("change", ".checkbox input[type=checkbox]", function() { $(this).blur(); })
+ .on("keydown paste", ".form-control", function(e) {
+ if(_isChar(e)) {
+ $(this).removeClass("empty");
+ }
+ })
+ .on("keyup change", ".form-control", function() {
+ var $this = $(this);
+ if($this.val() === "") {
+ $this.addClass("empty");
+ } else {
+ $this.removeClass("empty");
+ }
+ })
+ .on("focus", ".form-control-wrapper.fileinput", function() {
+ $(this).find("input").addClass("focus");
+ })
+ .on("blur", ".form-control-wrapper.fileinput", function() {
+ $(this).find("input").removeClass("focus");
+ })
+ .on("change", ".form-control-wrapper.fileinput [type=file]", function() {
+ var value = "";
+ $.each($(this)[0].files, function(i, file) {
+ console.log(file);
+ value += file.name + ", ";
+ });
+ value = value.substring(0, value.length - 2);
+ if (value) {
+ $(this).prev().removeClass("empty");
+ } else {
+ $(this).prev().addClass("empty");
+ }
+ $(this).prev().val(value);
+ });
+ },
+ "ripples": function(selector) {
+ $.ripples({"target": (selector) ? selector : this.options.withRipples});
+ },
+ "init": function() {
+ this.ripples();
+ this.input();
+ this.checkbox();
+ this.radio();
+
+ if (document.arrive) {
+ document.arrive("input, textarea, select", function() {
+ $.material.init();
+ });
+ }
+
+ // Detect autofill
+ (function() {
+ // This part of code will detect autofill when the page is loading (username and password inputs for example)
+ var loading = setInterval(function() {
+ $("input[type!=checkbox]").each(function() {
+ if ($(this).val() && $(this).val() !== $(this).attr("value")) {
+ $(this).trigger("change");
+ }
+ });
+ }, 100);
+ // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
+ setTimeout(function() {
+ clearInterval(loading);
+ }, 10000);
+ // Now we just listen on inputs of the focused form (because user can select from the autofill dropdown only when the input has focus)
+ var focused;
+ $(document)
+ .on("focus", "input", function() {
+ var $inputs = $(this).parents("form").find("input");
+ focused = setInterval(function() {
+ $inputs.each(function() {
+ if ($(this).val() !== $(this).attr("value")) {
+ $(this).trigger("change");
+ }
+ });
+ }, 100);
+ })
+ .on("blur", "input", function() {
+ clearInterval(focused);
+ });
+
+ })();
+ }
+ };
})(jQuery);
diff --git a/scripts/ripples.js b/scripts/ripples.js
index 0f10784b..399c4fdf 100644
--- a/scripts/ripples.js
+++ b/scripts/ripples.js
@@ -1,189 +1,105 @@
/* Copyright 2014+, Federico Zivolo, LICENSE at https://github.com/FezVrasta/bootstrap-material-design/blob/master/LICENSE.md */
-/* globals CustomEvent */
-window.ripples = {
- done: false,
- init : function(withRipple) {
- "use strict";
+/* globals jQuery */
- if (this.done) {
- return console.log("Ripples.js was already initialzied.");
- }
+(function($) {
+ $.ripples = function(options) {
- this.done = true;
+ // Default options
+ var defaultOptions = {
+ "target": ".btn:not(.btn-link), .card-image, .navbar a:not(.withoutripple), .nav-tabs a:not(.withoutripple), .withripple"
+ };
- // Cross browser matches function
- function matchesSelector(domElement, selector) {
- var matches = domElement.matches ||
- domElement.matchesSelector ||
- domElement.webkitMatchesSelector ||
- domElement.mozMatchesSelector ||
- domElement.msMatchesSelector ||
- domElement.oMatchesSelector;
- return matches.call(domElement, selector);
- }
+ // Fade out the ripple and then destroy it
+ function rippleOut(ripple) {
- // animations time
- var rippleOutTime = 100,
- rippleStartTime = 500;
+ // Unbind events from ripple
+ ripple.off();
- // Helper to bind events on dynamically created elements
- var bind = function(events, selector, callback) {
- if (typeof events === "string") {
- events = [events];
- }
- events.forEach(function(event) {
- document.addEventListener(event, function(e) {
- var target = (typeof e.detail !== "number") ? e.detail : e.target;
+ // Start the out animation
+ ripple.addClass("ripple-out");
- if (matchesSelector(target, selector)) {
- callback(e, target);
- }
- });
- });
- };
-
- var rippleStart = function(e, target, callback) {
-
- // Init variables
- var $rippleWrapper = target,
- $el = $rippleWrapper.parentNode,
- $ripple = document.createElement("div"),
- elPos = $el.getBoundingClientRect(),
- // Mouse pos in most cases
- mousePos = {x: e.clientX - elPos.left, y: ((window.ontouchstart) ? e.clientY - window.scrollY: e.clientY) - elPos.top},
- scale = "scale(" + Math.round($rippleWrapper.offsetWidth / 5) + ")",
- rippleEnd = new CustomEvent("rippleEnd", {detail: $ripple}),
- _rippleOpacity = 0.3,
- refreshElementStyle;
-
-
- // If multitouch is detected or some other black magic suff is happening...
- if (e.touches) {
- mousePos = {x: e.touches[0].clientX - elPos.left, y: e.touches[0].clientY - elPos.top};
- }
-
- $ripplecache = $ripple;
-
- // Set ripple class
- $ripple.className = "ripple";
-
- // Move ripple to the mouse position
- $ripple.setAttribute("style", "left:" + mousePos.x + "px; top:" + mousePos.y + "px;");
-
- // Get the clicked target's text color, this will be applied to the ripple as background-color.
- var targetColor = window.getComputedStyle($el).color;
-
- // Convert the rgb color to an rgba color with opacity set to __rippleOpacity__
- if ( targetColor.indexOf("rgba") >= 0 ) {
- var alphaPosition = targetColor.lastIndexOf(",") + 1;
- targetColor = targetColor.substring(0, alphaPosition) + _rippleOpacity + ")";
- } else {
- targetColor = targetColor.replace("rgb", "rgba").replace(")", ", " + _rippleOpacity + ")");
- }
-
- // Insert new ripple into ripple wrapper
- $rippleWrapper.appendChild($ripple);
-
- // Make sure the ripple has the class applied (ugly hack but it works)
- refreshElementStyle = window.getComputedStyle($ripple).opacity;
-
- // Let other funtions know that this element is animating
- $ripple.dataset.animating = 1;
-
- // Set scale value, background-color and opacity to ripple and animate it
- $ripple.className = "ripple ripple-on";
-
- // Prepare the style of the ripple
- var rippleStyle = [
- $ripple.getAttribute("style"),
- "background-color: " + targetColor,
- "-ms-transform: " + scale,
- "-moz-transform:" + scale,
- "-webkit-transform:" + scale,
- "transform: " + scale
- ];
-
- // Apply the style
- $ripple.setAttribute("style", rippleStyle.join(";"));
-
- // This function is called when the animation is finished
- setTimeout(function() {
-
- // Let know to other functions that this element has finished the animation
- $ripple.dataset.animating = 0;
- document.dispatchEvent(rippleEnd);
- if (callback) {
- callback();
- }
-
- }, rippleStartTime);
-
- };
-
- var rippleOut = function($ripple) {
- // Clear previous animation
- $ripple.className = "ripple ripple-on ripple-out";
-
- // Let ripple fade out (with CSS)
- setTimeout(function() {
- $ripple.remove();
- }, rippleOutTime);
- };
-
- // Helper, need to know if mouse is up or down
- var mouseDown = false;
- bind(["mousedown", "touchstart"], "*", function() {
- mouseDown = true;
- });
- bind(["mouseup", "touchend", "mouseout"], "*", function() {
- mouseDown = false;
- });
-
- // Append ripple wrapper if not exists already
- var rippleInit = function(e, target) {
- if (target.getElementsByClassName("ripple-wrapper").length === 0) {
- target.className += " withripple";
- var $rippleWrapper = document.createElement("div");
- $rippleWrapper.className = "ripple-wrapper";
- target.appendChild($rippleWrapper);
- }
- };
-
- var $ripplecache;
-
- // Events handler
- // init RippleJS and start ripple effect on mousedown
- bind(["mouseover"], withRipple, rippleInit);
-
- // Init if the device is touch screen
- bind(["touchstart"], withRipple, rippleInit);
-
- // start ripple effect on mousedown
- bind(["mousedown", "touchstart"], ".ripple-wrapper", function(e, $ripple) {
- // Start ripple only on left or middle mouse click and touch click
- if (e.which === 0 || e.which === 1 || e.which === 2) {
- rippleStart(e, $ripple);
- }
- });
-
- // if animation ends and user is not holding mouse then destroy the ripple
- bind("rippleEnd", ".ripple-wrapper .ripple", function(e, $ripple) {
-
- var $ripples = $ripple.parentNode.getElementsByClassName("ripple");
-
- if (!mouseDown || ( $ripples[0] == $ripple && $ripples.length > 1)) {
- rippleOut($ripple);
- }
- });
-
- // Destroy ripple when mouse is not holded anymore if the ripple still exists
- bind(["mouseup", "touchend", "mouseout"], ".ripple-wrapper", function() {
- var $ripple = $ripplecache;
- if ($ripple && $ripple.dataset.animating != 1) {
- rippleOut($ripple);
- }
- });
+ // This function is called when the transition "out" ends
+ ripple.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
+ ripple.remove();
+ });
}
-};
+
+ // Apply custom options
+ options = $.extend(defaultOptions, options);
+
+
+ $(document)
+ .on("mousedown", options.target, function(e) {
+ // If the ripple wrapper does not exists, create it
+ if (!$(this).find(".ripple-wrapper").length) {
+ $(this).append("");
+ }
+
+ var wrapper = $(this).find(".ripple-wrapper");
+
+ // Get the mouse position relative to the ripple wrapper
+ var wrapperOffset = wrapper.offset();
+ var relX = e.pageX - wrapperOffset.left;
+ var relY = e.pageY - wrapperOffset.top;
+
+ // Meet the new ripple
+ var ripple = $("");
+
+ // Add to it the ripple class
+ ripple.addClass("ripple");
+
+ // Position it in the right place
+ ripple.css({"left": relX, "top": relY});
+
+ // Set the background color of the ripple
+ ripple.css({"background-color": window.getComputedStyle($(this)[0]).color});
+
+ // Spawn it
+ wrapper.append(ripple);
+
+ // Make sure the ripple has the styles applied (ugly hack but it works)
+ (function() { return window.getComputedStyle(ripple[0]).opacity; })();
+
+ // Set the new size
+ var size = (Math.max($(this).outerWidth(), $(this).outerHeight()) / ripple.outerWidth()) * 2.5;
+
+ ripple.css({
+ "-ms-transform": "scale(" + size + ")",
+ "-moz-transform": "scale(" + size + ")",
+ "-webkit-transform": "scale(" + size + ")",
+ "transform": "scale(" + size + ")"
+ });
+
+ // Start the transition
+ ripple.addClass("ripple-on");
+ ripple.data("animating", "on");
+ ripple.data("mousedown", "on");
+
+ // This function is called when the transition "on" ends
+ setTimeout(function() {
+ ripple.data("animating", "off");
+ if (ripple.data("mousedown") == "off") {
+ rippleOut(ripple);
+ }
+ }, 500);
+
+ // On mouseup or on mouseleave, set the mousedown flag to "off" and try to destroy the ripple
+ wrapper.on("mouseup mouseleave", function() {
+ ripple.data("mousedown", "off");
+ // If the transition "on" is finished then we can destroy the ripple with transition "out"
+ if (ripple.data("animating") == "off") {
+ rippleOut(ripple);
+ }
+ });
+
+ });
+
+ };
+
+ $.fn.ripples = function() {
+ $.ripples({"target": $(this)});
+ };
+
+})(jQuery);