cmpRipple = function(elements, options) {
  //TODO: add version/copyright notice + version tag
  //TODO: build encapsulated JS file
  //TODO: active state should listen on mousedown + stay triggered on click
  //TODO: destroy() function removing click event handlers
  //TODO: build animationEvent/rippleElement only once?
  //TODO: add init-class for elements to apply standard attributes
  //TODO: specify browser support
  //TODO: jQuery-object-checker in case someone forgets `[0]`

  'use strict';

  /* options */
  if (!options) {options = {};}

  if (!options.animationClass) { options.animationClass = 'cmp-ripple-animation'; }
  if (!options.bubble) { options.bubble = false; }


  //get browser prefixed animation event
  var animationEvent = stylePrefix('animationend');

  //check for element + animation event support
  if (elements && animationEvent) {

    //assume single element
    if (!(elements instanceof NodeList)) {
      elements = [elements];
    }

    for (var index = 0; index < elements.length; index++) {
      var rippleMe = elements[index];

      rippleMe.addEventListener("mousedown", function( clickEvent ) {

        startRipple(rippleMe, clickEvent);

      });

      var startRipple = function(element, clickEvent) {
        //prevent event bubbling
        if (!options.bubble) {
          clickEvent.stopPropagation();
        }

        //offset relation = (click offset - element offset) ÷ element dimension
        var offsetRel = {
          left : ( clickEvent.clientX - offset(clickEvent.target).left ) / clickEvent.target.offsetWidth,
          top  : ( clickEvent.clientY - offset(clickEvent.target).top ) / clickEvent.target.offsetHeight
        }

        //create element for ripple animation
        var ripple = document.createElement('span');
        ripple.className = options.animationClass;
        ripple.setAttribute('style','top: '+ offsetRel.top*100 +'%; left: '+ offsetRel.left*100 +'%;');

        //self-destruct after animation
        ripple.addEventListener(animationEvent, function(event) {
          //TODO: toggle removal only if button is up
          var ripple = event.target;
          rippleRemove(ripple);
        });

        //trigger animation
        clickEvent.target.insertBefore(ripple, clickEvent.target.firstChild);
      }

      var rippleRemove = function(ripple) {
        ripple.className += ' cmp-ripple-remove';

        ripple.addEventListener(stylePrefix('transitionend'), function(event) {
          ripple.parentNode.removeChild(ripple);
        });
      }


    }

  }
}

//helper function for element offset
//via https://youmightnotneedjquery.com
offset = function(element){
  var rect = element.getBoundingClientRect();
  /*
    note:

    we removed `document.body.scrollTop` and `document.body.scrollLeft` because
    these aren't respected – we need to checkback in IE

  */

  return offsetObject =
    {
      top: rect.top,
      left: rect.left
    }

}

/**
 * Testing on prefixes
 *
 * stolen from David Walsh here:
 * https://davidwalsh.name/css-animation-callback
 * originally stolen from Modernizr:
 *
 */
function stylePrefix(attributeName){
  var prefixStyleLookup = {
    'animationend': {
      'animation':'animationend',
      'WebkitAnimation':'webkitAnimationEnd'
    },
    'transitionend': {
      'transition':'transitionend',
      'WebkitTransition':'webkitTransitionEnd'
    }
  }

  var attribute;
  var el = document.createElement('fakeTestElement');
  for(attribute in prefixStyleLookup[attributeName]){
      if( el.style[attribute] !== undefined ){
          return prefixStyleLookup[attributeName][attribute];
      }
  }
}
@@ -1179,24 +1179,172 @@
 ickEvent);%0A%0A
+      rippleMe.addEventListener(%22mouseup%22, function( clickEvent ) %7B%0A        rippleRemove(clickEvent.target.querySelector('.cmp-ripple-animation'));%0A
       %7D);%0A%0A 
@@ -2100,250 +2100,8 @@
 );%0A%0A
-        //self-destruct after animation%0A        ripple.addEventListener(animationEvent, function(event) %7B%0A          //TODO: toggle removal only if button is up%0A          var ripple = event.target;%0A          rippleRemove(ripple);%0A        %7D);%0A%0A
     
@@ -2209,24 +2209,33 @@
 %0A      %7D%0A%0A  
+  %7D%0A    %0A
     var ripp
@@ -2260,26 +2260,24 @@
 n(ripple) %7B%0A
-  
       ripple
@@ -2312,20 +2312,22 @@
 emove';%0A
-%0A
+ 
    
+%0A 
      rip
@@ -2403,24 +2403,28 @@
         
-  ripple
+event.target
 .parentN
@@ -2443,19 +2443,23 @@
 ild(
-ripple
+event.target
 );%0A
-  
     
@@ -2468,18 +2468,8 @@
 %7D);%0A
-      %7D%0A%0A%0A
     

put remove on mouseup