material.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. (function($) {
  2. 'use strict';
  3. // Add wave effect.
  4. Drupal.behaviors.adminimal_material_wave_effect = {
  5. attach: function (context, settings) {
  6. // Init Waves
  7. $( ".action-links li a" ).addClass("waves-effect waves-button waves-float waves-classic");
  8. //$( ".form-actions input" ).addClass("waves-effect");
  9. //$( 'input[type="submit"]' ).addClass("waves-effect");
  10. $( "#navigation ul.tabs.primary li a" ).addClass("waves-effect waves-button waves-classic");
  11. $( "#navigation ul.tabs.secondary li a" ).addClass("waves-effect waves-button waves-classic");
  12. $( "#admin-menu a" ).addClass("waves-effect waves-button waves-light waves-classic");
  13. $( ".theme-info .operations a" ).addClass("waves-effect waves-button waves-classic");
  14. $( "table tbody td a" ).addClass("waves-effect waves-button waves-classic");
  15. }
  16. };
  17. })(jQuery);
  18. /*!
  19. * Waves v0.6.6
  20. * http://fian.my.id/Waves
  21. *
  22. * Copyright 2014 Alfiana E. Sibuea and other contributors
  23. * Released under the MIT license
  24. * https://github.com/fians/Waves/blob/master/LICENSE
  25. */
  26. ;(function(window, factory) {
  27. "use strict";
  28. // AMD. Register as an anonymous module. Wrap in function so we have access
  29. // to root via `this`.
  30. if (typeof define === "function" && define.amd) {
  31. define([], function() {
  32. return factory.apply(window);
  33. });
  34. }
  35. // Node. Does not work with strict CommonJS, but only CommonJS-like
  36. // environments that support module.exports, like Node.
  37. else if (typeof exports === "object") {
  38. module.exports = factory.call(window);
  39. }
  40. // Browser globals.
  41. else {
  42. window.Waves = factory.call(window);
  43. }
  44. })(typeof global === "object" ? global : this, function () {
  45. "use strict";
  46. var Waves = Waves || {};
  47. var $$ = document.querySelectorAll.bind(document);
  48. // Find exact position of element
  49. function isWindow(obj) {
  50. return obj !== null && obj === obj.window;
  51. }
  52. function getWindow(elem) {
  53. return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
  54. }
  55. function offset(elem) {
  56. var docElem, win,
  57. box = {top: 0, left: 0},
  58. doc = elem && elem.ownerDocument;
  59. docElem = doc.documentElement;
  60. if (typeof elem.getBoundingClientRect !== typeof undefined) {
  61. box = elem.getBoundingClientRect();
  62. }
  63. win = getWindow(doc);
  64. return {
  65. top: box.top + win.pageYOffset - docElem.clientTop,
  66. left: box.left + win.pageXOffset - docElem.clientLeft
  67. };
  68. }
  69. function convertStyle(obj) {
  70. var style = '';
  71. for (var a in obj) {
  72. if (obj.hasOwnProperty(a)) {
  73. style += (a + ':' + obj[a] + ';');
  74. }
  75. }
  76. return style;
  77. }
  78. var Effect = {
  79. // Effect delay
  80. duration: 750,
  81. show: function(e, element) {
  82. // Disable right click
  83. if (e.button === 2) {
  84. return false;
  85. }
  86. var el = element || this;
  87. // Create ripple
  88. var ripple = document.createElement('div');
  89. ripple.className = 'waves-ripple';
  90. el.appendChild(ripple);
  91. // Get click coordinate and element witdh
  92. var pos = offset(el);
  93. var relativeY = (e.pageY - pos.top);
  94. var relativeX = (e.pageX - pos.left);
  95. var scale = 'scale('+((el.clientWidth / 100) * 3)+')';
  96. // Support for touch devices
  97. if ('touches' in e) {
  98. relativeY = (e.touches[0].pageY - pos.top);
  99. relativeX = (e.touches[0].pageX - pos.left);
  100. }
  101. // Attach data to element
  102. ripple.setAttribute('data-hold', Date.now());
  103. ripple.setAttribute('data-scale', scale);
  104. ripple.setAttribute('data-x', relativeX);
  105. ripple.setAttribute('data-y', relativeY);
  106. // Set ripple position
  107. var rippleStyle = {
  108. 'top': relativeY+'px',
  109. 'left': relativeX+'px'
  110. };
  111. ripple.className = ripple.className + ' waves-notransition';
  112. ripple.setAttribute('style', convertStyle(rippleStyle));
  113. ripple.className = ripple.className.replace('waves-notransition', '');
  114. // Scale the ripple
  115. rippleStyle['-webkit-transform'] = scale;
  116. rippleStyle['-moz-transform'] = scale;
  117. rippleStyle['-ms-transform'] = scale;
  118. rippleStyle['-o-transform'] = scale;
  119. rippleStyle.transform = scale;
  120. rippleStyle.opacity = '1';
  121. rippleStyle['-webkit-transition-duration'] = Effect.duration + 'ms';
  122. rippleStyle['-moz-transition-duration'] = Effect.duration + 'ms';
  123. rippleStyle['-o-transition-duration'] = Effect.duration + 'ms';
  124. rippleStyle['transition-duration'] = Effect.duration + 'ms';
  125. ripple.setAttribute('style', convertStyle(rippleStyle));
  126. },
  127. hide: function(e) {
  128. TouchHandler.touchup(e);
  129. var el = this;
  130. var width = el.clientWidth * 1.4;
  131. // Get first ripple
  132. var ripple = null;
  133. var ripples = el.getElementsByClassName('waves-ripple');
  134. if (ripples.length > 0) {
  135. ripple = ripples[ripples.length - 1];
  136. } else {
  137. return false;
  138. }
  139. var relativeX = ripple.getAttribute('data-x');
  140. var relativeY = ripple.getAttribute('data-y');
  141. var scale = ripple.getAttribute('data-scale');
  142. // Get delay beetween mousedown and mouse leave
  143. var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
  144. var delay = 350 - diff;
  145. if (delay < 0) {
  146. delay = 0;
  147. }
  148. // Fade out ripple after delay
  149. setTimeout(function() {
  150. var style = {
  151. 'top': relativeY+'px',
  152. 'left': relativeX+'px',
  153. 'opacity': '0',
  154. // Duration
  155. '-webkit-transition-duration': Effect.duration + 'ms',
  156. '-moz-transition-duration': Effect.duration + 'ms',
  157. '-o-transition-duration': Effect.duration + 'ms',
  158. 'transition-duration': Effect.duration + 'ms',
  159. '-webkit-transform': scale,
  160. '-moz-transform': scale,
  161. '-ms-transform': scale,
  162. '-o-transform': scale,
  163. 'transform': scale
  164. };
  165. ripple.setAttribute('style', convertStyle(style));
  166. setTimeout(function() {
  167. try {
  168. el.removeChild(ripple);
  169. } catch(e) {
  170. return false;
  171. }
  172. }, Effect.duration);
  173. }, delay);
  174. },
  175. // Little hack to make <input> can perform waves effect
  176. wrapInput: function(elements) {
  177. for (var a = 0; a < elements.length; a++) {
  178. var el = elements[a];
  179. if (el.tagName.toLowerCase() === 'input') {
  180. var parent = el.parentNode;
  181. // If input already have parent just pass through
  182. if (parent.tagName.toLowerCase() === 'i' && parent.className.indexOf('waves-effect') !== -1) {
  183. continue;
  184. }
  185. // Put element class and style to the specified parent
  186. var wrapper = document.createElement('i');
  187. wrapper.className = el.className + ' waves-input-wrapper';
  188. var elementStyle = el.getAttribute('style');
  189. if (!elementStyle) {
  190. elementStyle = '';
  191. }
  192. wrapper.setAttribute('style', elementStyle);
  193. el.className = 'waves-button-input';
  194. el.removeAttribute('style');
  195. // Put element as child
  196. parent.replaceChild(wrapper, el);
  197. wrapper.appendChild(el);
  198. }
  199. }
  200. }
  201. };
  202. /**
  203. * Disable mousedown event for 500ms during and after touch
  204. */
  205. var TouchHandler = {
  206. /* uses an integer rather than bool so there's no issues with
  207. * needing to clear timeouts if another touch event occurred
  208. * within the 500ms. Cannot mouseup between touchstart and
  209. * touchend, nor in the 500ms after touchend. */
  210. touches: 0,
  211. allowEvent: function(e) {
  212. var allow = true;
  213. if (e.type === 'touchstart') {
  214. TouchHandler.touches += 1; //push
  215. } else if (e.type === 'touchend' || e.type === 'touchcancel') {
  216. setTimeout(function() {
  217. if (TouchHandler.touches > 0) {
  218. TouchHandler.touches -= 1; //pop after 500ms
  219. }
  220. }, 500);
  221. } else if (e.type === 'mousedown' && TouchHandler.touches > 0) {
  222. allow = false;
  223. }
  224. return allow;
  225. },
  226. touchup: function(e) {
  227. TouchHandler.allowEvent(e);
  228. }
  229. };
  230. /**
  231. * Delegated click handler for .waves-effect element.
  232. * returns null when .waves-effect element not in "click tree"
  233. */
  234. function getWavesEffectElement(e) {
  235. if (TouchHandler.allowEvent(e) === false) {
  236. return null;
  237. }
  238. var element = null;
  239. var target = e.target || e.srcElement;
  240. while (target.parentElement !== null) {
  241. if (!(target instanceof SVGElement) && target.className.indexOf('waves-effect') !== -1) {
  242. element = target;
  243. break;
  244. } else if (target.classList.contains('waves-effect')) {
  245. element = target;
  246. break;
  247. }
  248. target = target.parentElement;
  249. }
  250. return element;
  251. }
  252. /**
  253. * Bubble the click and show effect if .waves-effect elem was found
  254. */
  255. function showEffect(e) {
  256. var element = getWavesEffectElement(e);
  257. if (element !== null) {
  258. Effect.show(e, element);
  259. if ('ontouchstart' in window) {
  260. element.addEventListener('touchend', Effect.hide, false);
  261. element.addEventListener('touchcancel', Effect.hide, false);
  262. }
  263. element.addEventListener('mouseup', Effect.hide, false);
  264. element.addEventListener('mouseleave', Effect.hide, false);
  265. }
  266. }
  267. Waves.displayEffect = function(options) {
  268. options = options || {};
  269. if ('duration' in options) {
  270. Effect.duration = options.duration;
  271. }
  272. //Wrap input inside <i> tag
  273. Effect.wrapInput($$('.waves-effect'));
  274. if ('ontouchstart' in window) {
  275. document.body.addEventListener('touchstart', showEffect, false);
  276. }
  277. document.body.addEventListener('mousedown', showEffect, false);
  278. };
  279. /**
  280. * Attach Waves to an input element (or any element which doesn't
  281. * bubble mouseup/mousedown events).
  282. * Intended to be used with dynamically loaded forms/inputs, or
  283. * where the user doesn't want a delegated click handler.
  284. */
  285. Waves.attach = function(element) {
  286. //FUTURE: automatically add waves classes and allow users
  287. // to specify them with an options param? Eg. light/classic/button
  288. if (element.tagName.toLowerCase() === 'input') {
  289. Effect.wrapInput([element]);
  290. element = element.parentElement;
  291. }
  292. if ('ontouchstart' in window) {
  293. element.addEventListener('touchstart', showEffect, false);
  294. }
  295. element.addEventListener('mousedown', showEffect, false);
  296. };
  297. return Waves;
  298. });
  299. // Init Waves
  300. (function ($) {
  301. Drupal.behaviors.wavesInit = {
  302. attach: function (context, settings) {
  303. Waves.displayEffect();
  304. }
  305. };
  306. })(jQuery);