From 1db10efb6245a6dc933c161d4613bcf95cfd9fc8 Mon Sep 17 00:00:00 2001 From: Fez Vrasta Date: Mon, 25 Aug 2014 13:05:03 +0200 Subject: [PATCH] Create ripples.js --- material/ripples.js | 110 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 material/ripples.js diff --git a/material/ripples.js b/material/ripples.js new file mode 100644 index 00000000..4336dbe3 --- /dev/null +++ b/material/ripples.js @@ -0,0 +1,110 @@ +/* globals CustomEvent */ +var ripples = { + init : function(withRipple) { + "use strict"; + + // Helper to bind events on dynamically created elements + var bind = function(event, selector, callback) { + document.addEventListener(event, function(e) { + var target = (typeof e.detail !== "number") ? e.detail : e.target; + + if (target.matches(selector)) { + callback(e, target); + } + }); + }; + + var rippleStart = function(e, target) { + + // Init variables + var $rippleWrapper = (target.matches(".ripple-wrapper")) ? target : target.parentNode, + $el = $rippleWrapper.parentNode, + $ripple = document.createElement("div"), + elPos = $el.getBoundingClientRect(), + mousePos = {x: e.clientX - elPos.left, y: e.clientY - elPos.top}, + scale = "transform:scale(" + Math.round($rippleWrapper.offsetWidth / 5) + ")", + rippleEnd = new CustomEvent("rippleEnd", {detail: $ripple}), + refreshElementStyle; + + // Set ripple class + $ripple.className = "ripple"; + + // Move ripple to the mouse position + $ripple.setAttribute("style", "left:" + mousePos.x + "px; top:" + mousePos.y + "px;"); + + // 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 to ripple and animate it + $ripple.className = "ripple ripple-on"; + $ripple.setAttribute("style", $ripple.getAttribute("style") + ["-ms-" + scale,"-moz-" + scale,"-webkit-" + scale,scale].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); + + }, 500); + + }; + + var rippleOut = function($ripple) { + // Clear previous animation + $ripple.className = "ripple ripple-on ripple-out"; + + // Let ripple fade out (with CSS) + setTimeout(function() { + $ripple.remove(); + }, 1000); + }; + + // Helper, need to know if mouse is up or down + var mouseDown = false; + document.body.onmousedown = function() { + mouseDown = true; + }; + document.body.onmouseup = 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); + rippleStart(e, $rippleWrapper); + } + + }; + + // Events handler + // init RippleJS and start ripple effect on mousedown + bind("mousedown", withRipple, rippleInit); + // start ripple effect on mousedown + bind("mousedown", ".ripple-wrapper, .ripple", rippleStart); + // if animation ends and user is not holding mouse then destroy the ripple + bind("rippleEnd", ".ripple-wrapper, .ripple", function(e, $ripple) { + if (!mouseDown) { + rippleOut($ripple); + } + }); + // Destroy ripple when mouse is not holded anymore if the ripple still exists + bind("mouseup", ".ripple-wrapper, .ripple", function(e, $ripple) { + if ($ripple.dataset.animating != 1) { + rippleOut($ripple); + } + }); + + } +};