summaryrefslogtreecommitdiff
path: root/static/js
diff options
context:
space:
mode:
Diffstat (limited to 'static/js')
-rw-r--r--static/js/material.js226
-rw-r--r--static/js/material.min.js2
-rw-r--r--static/js/material.min.js.map1
-rw-r--r--static/js/ripples.js324
-rw-r--r--static/js/ripples.min.js2
-rw-r--r--static/js/ripples.min.js.map1
6 files changed, 556 insertions, 0 deletions
diff --git a/static/js/material.js b/static/js/material.js
new file mode 100644
index 0000000..8186a7a
--- /dev/null
+++ b/static/js/material.js
@@ -0,0 +1,226 @@
+/* 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;
+ }
+
+ $.material = {
+ "options": {
+ // These options set what will be started by $.material.init()
+ "input": true,
+ "ripples": true,
+ "checkbox": true,
+ "togglebutton": true,
+ "radio": true,
+ "arrive": true,
+ "autofill": false,
+
+ "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]",
+ "togglebuttonElements": ".togglebutton > 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("<span class=ripple></span><span class=check></span>");
+ },
+ "togglebutton": function(selector) {
+ // Add fake-checkbox to material checkboxes
+ $((selector) ? selector : this.options.togglebuttonElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("<span class=toggle></span>");
+ },
+ "radio": function(selector) {
+ // Add fake-radio to material radios
+ $((selector) ? selector : this.options.radioElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .after("<span class=circle></span><span class=check></span>");
+ },
+ "input": function(selector) {
+ $((selector) ? selector : this.options.inputElements)
+ .filter(":notmdproc")
+ .data("mdproc", true)
+ .each( function() {
+ var $this = $(this);
+
+ if (!$(this).attr("data-hint") && !$this.hasClass("floating-label")) {
+ return;
+ }
+ $this.wrap("<div class=form-control-wrapper></div>");
+ $this.after("<span class=material-input></span>");
+
+ // Add floating label if required
+ if ($this.hasClass("floating-label")) {
+ var placeholder = $this.attr("placeholder");
+ $this.attr("placeholder", null).removeClass("floating-label");
+ $this.after("<div class=floating-label>" + placeholder + "</div>");
+ }
+
+ // Add hint label if required
+ if ($this.attr("data-hint")) {
+ $this.after("<div class=hint>" + $this.attr("data-hint") + "</div>");
+ }
+
+ // 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[0].checkValidity()) {
+ $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) {
+ 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) {
+ $((selector) ? selector : this.options.withRipples).ripples();
+ },
+ "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").not("[type=file]");
+ focused = setInterval(function() {
+ $inputs.each(function() {
+ if ($(this).val() !== $(this).attr("value")) {
+ $(this).trigger("change");
+ }
+ });
+ }, 100);
+ })
+ .on("blur", "input", function() {
+ clearInterval(focused);
+ });
+ },
+ "init": function() {
+ if ($.fn.ripples && this.options.ripples) {
+ this.ripples();
+ }
+ if (this.options.input) {
+ this.input();
+ }
+ if (this.options.checkbox) {
+ this.checkbox();
+ }
+ if (this.options.togglebutton) {
+ this.togglebutton();
+ }
+ if (this.options.radio) {
+ this.radio();
+ }
+ if (this.options.autofill) {
+ this.autofill();
+ }
+
+ if (document.arrive && this.options.arrive) {
+ if ($.fn.ripples && this.options.ripples) {
+ $(document).arrive(this.options.withRipples, function() {
+ $.material.ripples($(this));
+ });
+ }
+ if (this.options.input) {
+ $(document).arrive(this.options.inputElements, function() {
+ $.material.input($(this));
+ });
+ }
+ if (this.options.checkbox) {
+ $(document).arrive(this.options.checkboxElements, function() {
+ $.material.checkbox($(this));
+ });
+ }
+ if (this.options.radio) {
+ $(document).arrive(this.options.radioElements, function() {
+ $.material.radio($(this));
+ });
+ }
+ if (this.options.togglebutton) {
+ $(document).arrive(this.options.togglebuttonElements, function() {
+ $.material.togglebutton($(this));
+ });
+ }
+
+ }
+ }
+ };
+
+})(jQuery);
diff --git a/static/js/material.min.js b/static/js/material.min.js
new file mode 100644
index 0000000..800bb7f
--- /dev/null
+++ b/static/js/material.min.js
@@ -0,0 +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:{input:!0,ripples:!0,checkbox:!0,togglebutton:!0,radio:!0,arrive:!0,autofill:!1,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]",togglebuttonElements:".togglebutton > 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("<span class=ripple></span><span class=check></span>")},togglebutton:function(b){a(b?b:this.options.togglebuttonElements).filter(":notmdproc").data("mdproc",!0).after("<span class=toggle></span>")},radio:function(b){a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("<span class=circle></span><span class=check></span>")},input:function(c){a(c?c:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this);if(a(this).attr("data-hint")||b.hasClass("floating-label")){if(b.wrap("<div class=form-control-wrapper></div>"),b.after("<span class=material-input></span>"),b.hasClass("floating-label")){var c=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label"),b.after("<div class=floating-label>"+c+"</div>")}if(b.attr("data-hint")&&b.after("<div class=hint>"+b.attr("data-hint")+"</div>"),(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[0].checkValidity()?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){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(b?b:this.options.withRipples).ripples()},autofill: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").not("[type=file]");c=setInterval(function(){b.each(function(){a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100)}).on("blur","input",function(){clearInterval(c)})},init:function(){a.fn.ripples&&this.options.ripples&&this.ripples(),this.options.input&&this.input(),this.options.checkbox&&this.checkbox(),this.options.togglebutton&&this.togglebutton(),this.options.radio&&this.radio(),this.options.autofill&&this.autofill(),document.arrive&&this.options.arrive&&(a.fn.ripples&&this.options.ripples&&a(document).arrive(this.options.withRipples,function(){a.material.ripples(a(this))}),this.options.input&&a(document).arrive(this.options.inputElements,function(){a.material.input(a(this))}),this.options.checkbox&&a(document).arrive(this.options.checkboxElements,function(){a.material.checkbox(a(this))}),this.options.radio&&a(document).arrive(this.options.radioElements,function(){a.material.radio(a(this))}),this.options.togglebutton&&a(document).arrive(this.options.togglebuttonElements,function(){a.material.togglebutton(a(this))}))}}}(jQuery);
+//# sourceMappingURL=material.min.js.map
diff --git a/static/js/material.min.js.map b/static/js/material.min.js.map
new file mode 100644
index 0000000..05248d3
--- /dev/null
+++ b/static/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","input","ripples","checkbox","togglebutton","radio","arrive","autofill","withRipples","join","inputElements","checkboxElements","togglebuttonElements","radioElements","selector","this","filter","after","each","$this","attr","hasClass","wrap","placeholder","removeClass","val","addClass","parent","next","is","$input","detach","document","on","blur","e","checkValidity","find","value","files","i","file","name","substring","length","prev","loading","setInterval","trigger","setTimeout","clearInterval","focused","$inputs","parents","not","init","fn","jQuery"],"mappings":"CAEA,SAAUA,GAUR,QAASC,GAAQC,GACf,MAAwB,mBAAbA,GAAIC,OACN,EACsB,gBAAbD,GAAIC,OAAqBD,EAAIC,MAAQ,GAC7CD,EAAIE,UAAYF,EAAIG,UAAYH,EAAII,QAAuB,GAAbJ,EAAIC,OAErD,EAdTH,EAAEO,KAAK,KAAKC,UAAY,SAASC,GAC/B,MAAIT,GAAES,GAAKC,KAAK,WACP,GAEA,GAaXV,EAAEW,UACAC,SAEEC,OAAS,EACTC,SAAW,EACXC,UAAY,EACZC,cAAgB,EAChBC,OAAS,EACTC,QAAU,EACVC,UAAY,EAEZC,aACE,sBACA,cACA,gCACA,mBACA,kCACA,eACAC,KAAK,KACPC,cAAiB,iEACjBC,iBAAoB,2CACpBC,qBAAwB,+CACxBC,cAAiB,sCAEnBV,SAAY,SAASW,GAEnB1B,EAAE,EAAa0B,EAAWC,KAAKf,QAAQW,kBACtCK,OAAO,cACPlB,KAAK,UAAU,GACfmB,MAAM,wDAETb,aAAgB,SAASU,GAEvB1B,EAAE,EAAa0B,EAAWC,KAAKf,QAAQY,sBACtCI,OAAO,cACPlB,KAAK,UAAU,GACfmB,MAAM,+BAETZ,MAAS,SAASS,GAEhB1B,EAAE,EAAa0B,EAAWC,KAAKf,QAAQa,eACtCG,OAAO,cACPlB,KAAK,UAAU,GACfmB,MAAM,wDAEThB,MAAS,SAASa,GAChB1B,EAAE,EAAa0B,EAAWC,KAAKf,QAAQU,eACtCM,OAAO,cACPlB,KAAK,UAAU,GACfoB,KAAM,WACL,GAAIC,GAAQ/B,EAAE2B,KAEd,IAAK3B,EAAE2B,MAAMK,KAAK,cAAiBD,EAAME,SAAS,kBAAlD,CAOA,GAJAF,EAAMG,KAAK,0CACXH,EAAMF,MAAM,sCAGRE,EAAME,SAAS,kBAAmB,CACpC,GAAIE,GAAcJ,EAAMC,KAAK,cAC7BD,GAAMC,KAAK,cAAe,MAAMI,YAAY,kBAC5CL,EAAMF,MAAM,6BAA+BM,EAAc,UAc3D,GAVIJ,EAAMC,KAAK,cACbD,EAAMF,MAAM,mBAAqBE,EAAMC,KAAK,aAAe,WAIzC,OAAhBD,EAAMM,OAAiC,aAAfN,EAAMM,OAAwC,KAAhBN,EAAMM,QAC9DN,EAAMO,SAAS,SAIbP,EAAMQ,SAASC,OAAOC,GAAG,eAAgB,CAC3CV,EAAMQ,SAASD,SAAS,YACxB,IAAII,GAASX,EAAMQ,SAASC,OAAOG,QACnCZ,GAAMF,MAAMa,OAIhB1C,EAAE4C,UACDC,GAAG,SAAU,iCAAkC,WAAa7C,EAAE2B,MAAMmB,SACpED,GAAG,gBAAiB,gBAAiB,SAASE,GAC1C9C,EAAQ8C,IACT/C,EAAE2B,MAAMS,YAAY,WAGvBS,GAAG,eAAgB,gBAAiB,WACnC,GAAId,GAAQ/B,EAAE2B,KACK,MAAhBI,EAAMM,OAAgBN,EAAM,GAAGiB,gBAChCjB,EAAMO,SAAS,SAEfP,EAAMK,YAAY,WAGrBS,GAAG,QAAS,kCAAmC,WAC9C7C,EAAE2B,MAAMsB,KAAK,SAASX,SAAS,WAEhCO,GAAG,OAAQ,kCAAmC,WAC7C7C,EAAE2B,MAAMsB,KAAK,SAASb,YAAY,WAEnCS,GAAG,SAAU,8CAA+C,WAC3D,GAAIK,GAAQ,EACZlD,GAAE8B,KAAK9B,EAAE2B,MAAM,GAAGwB,MAAO,SAASC,EAAGC,GACnCH,GAASG,EAAKC,KAAO,OAEvBJ,EAAQA,EAAMK,UAAU,EAAGL,EAAMM,OAAS,GACtCN,EACFlD,EAAE2B,MAAM8B,OAAOrB,YAAY,SAE3BpC,EAAE2B,MAAM8B,OAAOnB,SAAS,SAE1BtC,EAAE2B,MAAM8B,OAAOpB,IAAIa,MAGvBpC,QAAW,SAASY,GAClB1B,EAAE,EAAa0B,EAAWC,KAAKf,QAAQQ,aAAaN,WAEtDK,SAAY,WAGV,GAAIuC,GAAUC,YAAY,WACxB3D,EAAE,yBAAyB8B,KAAK,WAC1B9B,EAAE2B,MAAMU,OAASrC,EAAE2B,MAAMU,QAAUrC,EAAE2B,MAAMK,KAAK,UAClDhC,EAAE2B,MAAMiC,QAAQ,aAGnB,IAGHC,YAAW,WACTC,cAAcJ,IACb,IAEH,IAAIK,EACJ/D,GAAE4C,UACDC,GAAG,QAAS,QAAS,WACpB,GAAImB,GAAUhE,EAAE2B,MAAMsC,QAAQ,QAAQhB,KAAK,SAASiB,IAAI,cACxDH,GAAUJ,YAAY,WACpBK,EAAQlC,KAAK,WACP9B,EAAE2B,MAAMU,QAAUrC,EAAE2B,MAAMK,KAAK,UACjChC,EAAE2B,MAAMiC,QAAQ,aAGnB,OAEJf,GAAG,OAAQ,QAAS,WACnBiB,cAAcC,MAGlBI,KAAQ,WACFnE,EAAEoE,GAAGtD,SAAWa,KAAKf,QAAQE,SAC/Ba,KAAKb,UAEHa,KAAKf,QAAQC,OACfc,KAAKd,QAEHc,KAAKf,QAAQG,UACfY,KAAKZ,WAEHY,KAAKf,QAAQI,cACfW,KAAKX,eAEHW,KAAKf,QAAQK,OACfU,KAAKV,QAEHU,KAAKf,QAAQO,UACfQ,KAAKR,WAGHyB,SAAS1B,QAAUS,KAAKf,QAAQM,SAC9BlB,EAAEoE,GAAGtD,SAAWa,KAAKf,QAAQE,SAC/Bd,EAAE4C,UAAU1B,OAAOS,KAAKf,QAAQQ,YAAa,WAC3CpB,EAAEW,SAASG,QAAQd,EAAE2B,SAGrBA,KAAKf,QAAQC,OACfb,EAAE4C,UAAU1B,OAAOS,KAAKf,QAAQU,cAAe,WAC7CtB,EAAEW,SAASE,MAAMb,EAAE2B,SAGnBA,KAAKf,QAAQG,UACff,EAAE4C,UAAU1B,OAAOS,KAAKf,QAAQW,iBAAkB,WAChDvB,EAAEW,SAASI,SAASf,EAAE2B,SAGtBA,KAAKf,QAAQK,OACfjB,EAAE4C,UAAU1B,OAAOS,KAAKf,QAAQa,cAAe,WAC7CzB,EAAEW,SAASM,MAAMjB,EAAE2B,SAGnBA,KAAKf,QAAQI,cACfhB,EAAE4C,UAAU1B,OAAOS,KAAKf,QAAQY,qBAAsB,WACpDxB,EAAEW,SAASK,aAAahB,EAAE2B,aAQnC0C"} \ No newline at end of file
diff --git a/static/js/ripples.js b/static/js/ripples.js
new file mode 100644
index 0000000..033d2ff
--- /dev/null
+++ b/static/js/ripples.js
@@ -0,0 +1,324 @@
+/* Copyright 2014+, Federico Zivolo, LICENSE at https://github.com/FezVrasta/bootstrap-material-design/blob/master/LICENSE.md */
+/* globals jQuery, navigator */
+
+(function($, window, document, undefined) {
+
+ "use strict";
+
+ /**
+ * Define the name of the plugin
+ */
+ var ripples = "ripples";
+
+
+ /**
+ * Get an instance of the plugin
+ */
+ var self = null;
+
+
+ /**
+ * Define the defaults of the plugin
+ */
+ var defaults = {};
+
+
+ /**
+ * Create the main plugin function
+ */
+ function Ripples(element, options) {
+ self = this;
+
+ this.element = $(element);
+
+ this.options = $.extend({}, defaults, options);
+
+ this._defaults = defaults;
+ this._name = ripples;
+
+ this.init();
+ }
+
+
+ /**
+ * Initialize the plugin
+ */
+ Ripples.prototype.init = function() {
+ var $element = this.element;
+
+ $element.on("mousedown touchstart", function(event) {
+ /**
+ * Verify if the user is just touching on a device and return if so
+ */
+ if(self.isTouch() && event.type === "mousedown") {
+ return false;
+ }
+
+
+ /**
+ * Verify if the current element already has a ripple wrapper element and
+ * creates if it doesn't
+ */
+ if(!($element.find(".ripple-wrapper").length)) {
+ $element.append("<div class=\"ripple-wrapper\"></div>");
+ }
+
+
+ /**
+ * Find the ripple wrapper
+ */
+ var $wrapper = $element.children(".ripple-wrapper");
+
+
+ /**
+ * Get relY and relX positions
+ */
+ var relY = self.getRelY($wrapper, event);
+ var relX = self.getRelX($wrapper, event);
+
+
+ /**
+ * If relY and/or relX are false, return the event
+ */
+ if(!relY && !relX) {
+ return;
+ }
+
+
+ /**
+ * Get the ripple color
+ */
+ var rippleColor = self.getRipplesColor($element);
+
+
+ /**
+ * Create the ripple element
+ */
+ var $ripple = $("<div></div>");
+
+ $ripple
+ .addClass("ripple")
+ .css({
+ "left": relX,
+ "top": relY,
+ "background-color": rippleColor
+ });
+
+
+ /**
+ * Append the ripple to the wrapper
+ */
+ $wrapper.append($ripple);
+
+
+ /**
+ * Make sure the ripple has the styles applied (ugly hack but it works)
+ */
+ (function() { return window.getComputedStyle($ripple[0]).opacity; })();
+
+
+ /**
+ * Turn on the ripple animation
+ */
+ self.rippleOn($element, $ripple);
+
+
+ /**
+ * Call the rippleEnd function when the transition "on" ends
+ */
+ setTimeout(function() {
+ self.rippleEnd($ripple);
+ }, 500);
+
+
+ /**
+ * Detect when the user leaves the element
+ */
+ $element.on("mouseup mouseleave touchend", function() {
+ $ripple.data("mousedown", "off");
+
+ if($ripple.data("animating") === "off") {
+ self.rippleOut($ripple);
+ }
+ });
+
+ });
+ };
+
+
+ /**
+ * Get the new size based on the element height/width and the ripple width
+ */
+ Ripples.prototype.getNewSize = function($element, $ripple) {
+
+ return (Math.max($element.outerWidth(), $element.outerHeight()) / $ripple.outerWidth()) * 2.5;
+ };
+
+
+ /**
+ * Get the relX
+ */
+ Ripples.prototype.getRelX = function($wrapper, event) {
+ var wrapperOffset = $wrapper.offset();
+
+ if(!self.isTouch()) {
+ /**
+ * Get the mouse position relative to the ripple wrapper
+ */
+ return event.pageX - wrapperOffset.left;
+ } else {
+ /**
+ * Make sure the user is using only one finger and then get the touch
+ * position relative to the ripple wrapper
+ */
+ event = event.originalEvent;
+
+ if(event.touches.length !== 1) {
+ return event.touches[0].pageX - wrapperOffset.left;
+ }
+
+ return false;
+ }
+ };
+
+
+ /**
+ * Get the relY
+ */
+ Ripples.prototype.getRelY = function($wrapper, event) {
+ var wrapperOffset = $wrapper.offset();
+
+ if(!self.isTouch()) {
+ /**
+ * Get the mouse position relative to the ripple wrapper
+ */
+ return event.pageY - wrapperOffset.top;
+ } else {
+ /**
+ * Make sure the user is using only one finger and then get the touch
+ * position relative to the ripple wrapper
+ */
+ event = event.originalEvent;
+
+ if(event.touches.length !== 1) {
+ return event.touches[0].pageY - wrapperOffset.top;
+ }
+
+ return false;
+ }
+ };
+
+
+ /**
+ * Get the ripple color
+ */
+ Ripples.prototype.getRipplesColor = function($element) {
+
+ var color = $element.data("ripple-color") ? $element.data("ripple-color") : window.getComputedStyle($element[0]).color;
+
+ return color;
+ };
+
+
+ /**
+ * Verify if the client browser has transistion support
+ */
+ Ripples.prototype.hasTransitionSupport = function() {
+ var thisBody = document.body || document.documentElement;
+ var thisStyle = thisBody.style;
+
+ var support = (
+ thisStyle.transition !== undefined ||
+ thisStyle.WebkitTransition !== undefined ||
+ thisStyle.MozTransition !== undefined ||
+ thisStyle.MsTransition !== undefined ||
+ thisStyle.OTransition !== undefined
+ );
+
+ return support;
+ };
+
+
+ /**
+ * Verify if the client is using a mobile device
+ */
+ Ripples.prototype.isTouch = function() {
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+ };
+
+
+ /**
+ * End the animation of the ripple
+ */
+ Ripples.prototype.rippleEnd = function($ripple) {
+ $ripple.data("animating", "off");
+
+ if($ripple.data("mousedown") === "off") {
+ self.rippleOut($ripple);
+ }
+ };
+
+
+ /**
+ * Turn off the ripple effect
+ */
+ Ripples.prototype.rippleOut = function($ripple) {
+ $ripple.off();
+
+ if(self.hasTransitionSupport()) {
+ $ripple.addClass("ripple-out");
+ } else {
+ $ripple.animate({"opacity": 0}, 100, function() {
+ $ripple.trigger("transitionend");
+ });
+ }
+
+ $ripple.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function() {
+ $ripple.remove();
+ });
+ };
+
+
+ /**
+ * Turn on the ripple effect
+ */
+ Ripples.prototype.rippleOn = function($element, $ripple) {
+ var size = self.getNewSize($element, $ripple);
+
+ if(self.hasTransitionSupport()) {
+ $ripple
+ .css({
+ "-ms-transform": "scale(" + size + ")",
+ "-moz-transform": "scale(" + size + ")",
+ "-webkit-transform": "scale(" + size + ")",
+ "transform": "scale(" + size + ")"
+ })
+ .addClass("ripple-on")
+ .data("animating", "on")
+ .data("mousedown", "on");
+ } else {
+ $ripple.animate({
+ "width": Math.max($element.outerWidth(), $element.outerHeight()) * 2,
+ "height": Math.max($element.outerWidth(), $element.outerHeight()) * 2,
+ "margin-left": Math.max($element.outerWidth(), $element.outerHeight()) * (-1),
+ "margin-top": Math.max($element.outerWidth(), $element.outerHeight()) * (-1),
+ "opacity": 0.2
+ }, 500, function() {
+ $ripple.trigger("transitionend");
+ });
+ }
+ };
+
+
+ /**
+ * Create the jquery plugin function
+ */
+ $.fn.ripples = function(options) {
+ return this.each(function() {
+ if(!$.data(this, "plugin_" + ripples)) {
+ $.data(this, "plugin_" + ripples, new Ripples(this, options));
+ }
+ });
+ };
+
+})(jQuery, window, document);
diff --git a/static/js/ripples.min.js b/static/js/ripples.min.js
new file mode 100644
index 0000000..ed0ec5d
--- /dev/null
+++ b/static/js/ripples.min.js
@@ -0,0 +1,2 @@
+!function(a,b,c,d){"use strict";function e(b,c){g=this,this.element=a(b),this.options=a.extend({},h,c),this._defaults=h,this._name=f,this.init()}var f="ripples",g=null,h={};e.prototype.init=function(){var c=this.element;c.on("mousedown touchstart",function(d){if(g.isTouch()&&"mousedown"===d.type)return!1;c.find(".ripple-wrapper").length||c.append('<div class="ripple-wrapper"></div>');var e=c.children(".ripple-wrapper"),f=g.getRelY(e,d),h=g.getRelX(e,d);if(f||h){var i=g.getRipplesColor(c),j=a("<div></div>");j.addClass("ripple").css({left:h,top:f,"background-color":i}),e.append(j),function(){return b.getComputedStyle(j[0]).opacity}(),g.rippleOn(c,j),setTimeout(function(){g.rippleEnd(j)},500),c.on("mouseup mouseleave touchend",function(){j.data("mousedown","off"),"off"===j.data("animating")&&g.rippleOut(j)})}})},e.prototype.getNewSize=function(a,b){return Math.max(a.outerWidth(),a.outerHeight())/b.outerWidth()*2.5},e.prototype.getRelX=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1!==b.touches.length?b.touches[0].pageX-c.left:!1):b.pageX-c.left},e.prototype.getRelY=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1!==b.touches.length?b.touches[0].pageY-c.top:!1):b.pageY-c.top},e.prototype.getRipplesColor=function(a){var c=a.data("ripple-color")?a.data("ripple-color"):b.getComputedStyle(a[0]).color;return c},e.prototype.hasTransitionSupport=function(){var a=c.body||c.documentElement,b=a.style,e=b.transition!==d||b.WebkitTransition!==d||b.MozTransition!==d||b.MsTransition!==d||b.OTransition!==d;return e},e.prototype.isTouch=function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},e.prototype.rippleEnd=function(a){a.data("animating","off"),"off"===a.data("mousedown")&&g.rippleOut(a)},e.prototype.rippleOut=function(a){a.off(),g.hasTransitionSupport()?a.addClass("ripple-out"):a.animate({opacity:0},100,function(){a.trigger("transitionend")}),a.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){a.remove()})},e.prototype.rippleOn=function(a,b){var c=g.getNewSize(a,b);g.hasTransitionSupport()?b.css({"-ms-transform":"scale("+c+")","-moz-transform":"scale("+c+")","-webkit-transform":"scale("+c+")",transform:"scale("+c+")"}).addClass("ripple-on").data("animating","on").data("mousedown","on"):b.animate({width:2*Math.max(a.outerWidth(),a.outerHeight()),height:2*Math.max(a.outerWidth(),a.outerHeight()),"margin-left":-1*Math.max(a.outerWidth(),a.outerHeight()),"margin-top":-1*Math.max(a.outerWidth(),a.outerHeight()),opacity:.2},500,function(){b.trigger("transitionend")})},a.fn.ripples=function(b){return this.each(function(){a.data(this,"plugin_"+f)||a.data(this,"plugin_"+f,new e(this,b))})}}(jQuery,window,document);
+//# sourceMappingURL=ripples.min.js.map \ No newline at end of file
diff --git a/static/js/ripples.min.js.map b/static/js/ripples.min.js.map
new file mode 100644
index 0000000..a59ce52
--- /dev/null
+++ b/static/js/ripples.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"ripples.min.js","sources":["ripples.js"],"names":["$","window","document","undefined","Ripples","element","options","self","this","extend","defaults","_defaults","_name","ripples","init","prototype","$element","on","event","isTouch","type","find","append","$wrapper","children","relY","getRelY","relX","getRelX","rippleColor","getRipplesColor","$ripple","addClass","css","left","top","background-color","getComputedStyle","opacity","rippleOn","setTimeout","rippleEnd","data","rippleOut","getNewSize","Math","max","outerWidth","outerHeight","wrapperOffset","offset","originalEvent","touches","length","pageX","pageY","color","hasTransitionSupport","thisBody","body","documentElement","thisStyle","style","support","transition","WebkitTransition","MozTransition","MsTransition","OTransition","test","navigator","userAgent","off","animate","trigger","remove","size","-ms-transform","-moz-transform","-webkit-transform","transform","width","height","margin-left","margin-top","fn","each","jQuery"],"mappings":"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"} \ No newline at end of file