From 8da7839ce0d12e2ec18a4780018ba91eda6d0461 Mon Sep 17 00:00:00 2001 From: guyskk Date: Wed, 19 Oct 2016 12:27:16 +0000 Subject: [PATCH] Improve vue-waves --- .babelrc | 3 + .gitignore | 1 + .jshintrc | 10 ++ README.md | 46 +++++-- demo/index.html | 79 ++++++++++++ dist/vue-waves.js | 1 + index.js | 20 +++ package.json | 55 ++++---- waves.css | 222 +++++++++++++++----------------- waves.js | 277 +++++++++++++++++++++++++++++++--------- webpack.config.babel.js | 15 +++ 11 files changed, 511 insertions(+), 218 deletions(-) create mode 100644 .babelrc create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 demo/index.html create mode 100644 dist/vue-waves.js create mode 100644 index.js create mode 100644 webpack.config.babel.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c13c5f6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..e99898a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,10 @@ +{ + "undef": true, + "unused": true, + "esversion": 6, + "asi": true, + "browser": true, + "node": true, + "devel": true, + "predef": ["Vue", "VueWaves"] +} diff --git a/README.md b/README.md index d7dfc78..a58b27a 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,51 @@ # vue-waves -> it's a vuejs version of waves Based on https://github.com/fians/Waves +A Vue.js version of waves based on https://github.com/fians/Waves. ## How to Use -``` bash -# install dependencies +### SetUp + +```bash npm install vue-waves ``` + then in the js file -``` javascript + +```javascript var Vue = require('vue') -var vueWaves = require('vue-waves'); +var VueWaves = require('vue-waves'); -Vue.use(vueWaves); +Vue.use(VueWaves); ``` -then in vue file +### Config + +```javascript +Vue.use(VueWaves, { + name: 'waves' // Vue指令名称 + duration: 500, // 涟漪效果持续时间 + delay: 200 // 延时显示涟漪效果 +}) +``` -``` html - -
- +### Usage + +```html + +``` + +Vue directive: +``` +v-waves.button 按钮 +v-waves.circle 圆形 +v-waves.block 块 +v-waves.float 阴影效果 +v-waves.light 亮色涟漪 +v-waves.classic ?? ``` +Demo: + git clone https://github.com/Teddy-Zhu/vue-waves.git + open vue-waves/demo/index.html diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..5a9a25f --- /dev/null +++ b/demo/index.html @@ -0,0 +1,79 @@ + + + + + + vue-waves + + + + + +
+

+ {{ message }} +

+
+ Vue Waves +
+
+ +
+
+ +
+
+ V +
+
+ V +
+
+ +
+
+ + + + + diff --git a/dist/vue-waves.js b/dist/vue-waves.js new file mode 100644 index 0000000..c753182 --- /dev/null +++ b/dist/vue-waves.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VueWaves=t():e.VueWaves=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}n(5);var o=n(1),i=r(o);e.exports={install:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{name:"waves"};e.directive(t.name,{inserted:function(e,t){var n=["button","circle","block","float","light","classic"].filter(function(e){return t.modifiers[e]}).map(function(e){return"waves-"+e});i["default"].attach(e,n)}}),e.mixin({created:function(){i["default"].init(t)}})}}},function(e,t,n){var r,o;(function(n){"use strict";var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(n,i){r=[],o=function(){return i.apply(n)}.apply(t,r),!(void 0!==o&&(e.exports=o))}("object"===("undefined"==typeof n?"undefined":i(n))?n:void 0,function(){function e(e){return null!==e&&e===e.window}function t(t){return e(t)?t:9===t.nodeType&&t.defaultView}function n(e){var t="undefined"==typeof e?"undefined":i(e);return"function"===t||"object"===t&&!!e}function r(e){return n(e)&&e.nodeType>0}function o(e){var t=p.call(e);return"[object String]"===t?f(e):n(e)&&/^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(t)&&e.hasOwnProperty("length")?e:r(e)?[e]:[]}function a(e){var n,r,o={top:0,left:0},a=e&&e.ownerDocument;return n=a.documentElement,"undefined"!==i(e.getBoundingClientRect)&&(o=e.getBoundingClientRect()),r=t(a),{top:o.top+r.pageYOffset-n.clientTop,left:o.left+r.pageXOffset-n.clientLeft}}function s(e){var t="";for(var n in e)e.hasOwnProperty(n)&&(t+=n+":"+e[n]+";");return t}function u(e,t,n){if(n){n.classList.remove("waves-rippling");var r=n.getAttribute("data-x"),o=n.getAttribute("data-y"),i=n.getAttribute("data-scale"),a=n.getAttribute("data-translate"),u=Date.now()-Number(n.getAttribute("data-hold")),l=350-u;l<0&&(l=0),"mousemove"===e.type&&(l=150);var c="mousemove"===e.type?2500:m.duration;setTimeout(function(){var e={top:o+"px",left:r+"px",opacity:"0","-webkit-transition-duration":c+"ms","-moz-transition-duration":c+"ms","-o-transition-duration":c+"ms","transition-duration":c+"ms","-webkit-transform":i+" "+a,"-moz-transform":i+" "+a,"-ms-transform":i+" "+a,"-o-transform":i+" "+a,transform:i+" "+a};n.setAttribute("style",s(e)),setTimeout(function(){try{t.removeChild(n)}catch(e){return!1}},c)},l)}}function l(e){if(b.allowEvent(e)===!1)return null;for(var t=null,n=e.target||e.srcElement;n.parentElement;){if(!(n instanceof SVGElement)&&n.classList.contains("waves-effect")){t=n;break}n=n.parentElement}return t}function c(e){var t=l(e);if(null!==t){if(t.disabled||t.getAttribute("disabled")||t.classList.contains("disabled"))return;if(b.registerEvent(e),"touchstart"===e.type&&m.delay){var n=!1,r=setTimeout(function(){r=null,m.show(e,t)},m.delay),o=function(o){r&&(clearTimeout(r),r=null,m.show(e,t)),n||(n=!0,m.hide(o,t)),a()},i=function(e){r&&(clearTimeout(r),r=null),o(e),a()};t.addEventListener("touchmove",i,!1),t.addEventListener("touchend",o,!1),t.addEventListener("touchcancel",o,!1);var a=function(){t.removeEventListener("touchmove",i),t.removeEventListener("touchend",o),t.removeEventListener("touchcancel",o)}}else m.show(e,t),v&&(t.addEventListener("touchend",m.hide,!1),t.addEventListener("touchcancel",m.hide,!1)),t.addEventListener("mouseup",m.hide,!1),t.addEventListener("mouseleave",m.hide,!1)}}var d=d||{},f=document.querySelectorAll.bind(document),p=Object.prototype.toString,v="ontouchstart"in window,m={duration:750,delay:200,show:function(e,t,n){if(2===e.button)return!1;t=t||this;var r=document.createElement("div");r.className="waves-ripple waves-rippling",t.appendChild(r);var o=a(t),i=0,u=0;"touches"in e&&e.touches.length?(i=e.touches[0].pageY-o.top,u=e.touches[0].pageX-o.left):(i=e.pageY-o.top,u=e.pageX-o.left),u=u>=0?u:0,i=i>=0?i:0;var l="scale("+t.clientWidth/100*3+")",c="translate(0,0)";n&&(c="translate("+n.x+"px, "+n.y+"px)"),r.setAttribute("data-hold",Date.now()),r.setAttribute("data-x",u),r.setAttribute("data-y",i),r.setAttribute("data-scale",l),r.setAttribute("data-translate",c);var d={top:i+"px",left:u+"px"};r.classList.add("waves-notransition"),r.setAttribute("style",s(d)),r.classList.remove("waves-notransition"),d["-webkit-transform"]=l+" "+c,d["-moz-transform"]=l+" "+c,d["-ms-transform"]=l+" "+c,d["-o-transform"]=l+" "+c,d.transform=l+" "+c,d.opacity="1";var f="mousemove"===e.type?2500:m.duration;d["-webkit-transition-duration"]=f+"ms",d["-moz-transition-duration"]=f+"ms",d["-o-transition-duration"]=f+"ms",d["transition-duration"]=f+"ms",r.setAttribute("style",s(d))},hide:function(e,t){t=t||this;for(var n=t.getElementsByClassName("waves-rippling"),r=0,o=n.length;r=0&&null!==t.wait){var f={type:"mouseup",button:1};setTimeout(d(f,r),t.wait)}},d.calm=function(e){e=o(e);for(var t={type:"mouseup",button:1},n=0,r=e.length;n=0&&w.splice(t,1)}function s(e){var t=document.createElement("style");return t.type="text/css",i(e,t),t}function u(e){var t=document.createElement("link");return t.rel="stylesheet",i(e,t),t}function l(e,t){var n,r,o;if(t.singleton){var i=g++;n=b||(b=s(t)),r=c.bind(null,n,i,!1),o=c.bind(null,n,i,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=u(t),r=f.bind(null,n),o=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(t),r=d.bind(null,n),o=function(){a(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}function c(e,t,n,r){var o=n?"":r.css;if(e.styleSheet)e.styleSheet.cssText=y(t,o);else{var i=document.createTextNode(o),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(i,a[t]):e.appendChild(i)}}function d(e,t){var n=t.css,r=t.media;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function f(e,t){var n=t.css,r=t.sourceMap;r&&(n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var o=new Blob([n],{type:"text/css"}),i=e.href;e.href=URL.createObjectURL(o),i&&URL.revokeObjectURL(i)}var p={},v=function(e){var t;return function(){return"undefined"==typeof t&&(t=e.apply(this,arguments)),t}},m=v(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),h=v(function(){return document.head||document.getElementsByTagName("head")[0]}),b=null,g=0,w=[];e.exports=function(e,t){t=t||{},"undefined"==typeof t.singleton&&(t.singleton=m()),"undefined"==typeof t.insertAt&&(t.insertAt="bottom");var n=o(e);return r(n,t),function(e){for(var i=[],a=0;a binding.modifiers[cls]) + .map(cls => `waves-${cls}`) + Waves.attach(el, classes) + } + }) + Vue.mixin({ + created: function() { + Waves.init(options); + } + }) + } +} diff --git a/package.json b/package.json index 8d0d479..54873d5 100644 --- a/package.json +++ b/package.json @@ -1,29 +1,30 @@ { - "name": "vue-waves", - "homepage": "http://www.eicoding.com", - "version": "0.0.5", - "description": "it's a vuejs version of waves", - "author": "teddyzhu", - "scripts": { - - }, - "dependencies": { - "vue": "^1.0.21", - "css-loader": "^0.23.1", - "cssnext-loader": "^1.0.1" - }, - "readme":"README.md", - "main": "waves.js", - "repository": { - "type": "git", - "url": "git@github.com:Teddy-Zhu/vue-waves.git" - }, - "license": "MIT", - "devDependencies": { - }, - "files": [ - "Readme.md", - "waves.js", - "waves.css" - ] + "name": "vue-waves", + "homepage": "https://github.com/Teddy-Zhu/vue-waves", + "version": "0.1.0", + "description": "A Vue.js version of waves", + "author": "teddyzhu", + "scripts": { + "build": "webpack -p" + }, + "dependencies": {}, + "readme": "README.md", + "main": "index.js", + "repository": { + "type": "git", + "url": "git@github.com:Teddy-Zhu/vue-waves.git" + }, + "license": "MIT", + "devDependencies": { + "babel-core": "^6.17.0", + "babel-loader": "^6.2.5", + "babel-preset-es2015": "^6.16.0", + "css-loader": "^0.25.0", + "style-loader": "^0.13.1", + "vue": "^2.0.3", + "webpack": "^1.13.2" + }, + "files": [ + "dist" + ] } diff --git a/waves.css b/waves.css index 38f5c62..0a28241 100644 --- a/waves.css +++ b/waves.css @@ -1,152 +1,136 @@ /*! -* Waves v0.7.5 -* http://fian.my.id/Waves -* -* Copyright 2014-2016 Alfiana E. Sibuea and other contributors -* Released under the MIT license -* https://github.com/fians/Waves/blob/master/LICENSE -*/ + * Waves v0.7.5 + * http://fian.my.id/Waves + * + * Copyright 2014-2016 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */ .waves-effect { - position: relative; - cursor: pointer; - display: inline-block; - overflow: hidden; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-tap-highlight-color: transparent; -} - + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; +} .waves-effect .waves-ripple { - position: absolute; - border-radius: 50%; - width: 100px; - height: 100px; - margin-top: -50px; - margin-left: -50px; - opacity: 0; - background: rgba(0, 0, 0, 0.2); - background: -webkit-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: -o-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: -moz-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - -webkit-transition: all 0.5s ease-out; - -moz-transition: all 0.5s ease-out; - -o-transition: all 0.5s ease-out; - transition: all 0.5s ease-out; - -webkit-transition-property: -webkit-transform, opacity; - -moz-transition-property: -moz-transform, opacity; - -o-transition-property: -o-transform, opacity; - transition-property: transform, opacity; - -webkit-transform: scale(0) translate(0, 0); - -moz-transform: scale(0) translate(0, 0); - -ms-transform: scale(0) translate(0, 0); - -o-transform: scale(0) translate(0, 0); - transform: scale(0) translate(0, 0); - pointer-events: none; -} - + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + margin-top: -50px; + margin-left: -50px; + opacity: 0; + background: rgba(0, 0, 0, 0.2); + background: -webkit-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -o-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -moz-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + -webkit-transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + -o-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; + -webkit-transition-property: -webkit-transform, opacity; + -moz-transition-property: -moz-transform, opacity; + -o-transition-property: -o-transform, opacity; + transition-property: transform, opacity; + -webkit-transform: scale(0) translate(0, 0); + -moz-transform: scale(0) translate(0, 0); + -ms-transform: scale(0) translate(0, 0); + -o-transform: scale(0) translate(0, 0); + transform: scale(0) translate(0, 0); + pointer-events: none; +} .waves-effect.waves-light .waves-ripple { - background: rgba(255, 255, 255, 0.4); - background: -webkit-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: -o-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: -moz-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); - background: radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: rgba(255, 255, 255, 0.4); + background: -webkit-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -o-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -moz-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); } - .waves-effect.waves-classic .waves-ripple { - background: rgba(0, 0, 0, 0.2); + background: rgba(0, 0, 0, 0.2); } - .waves-effect.waves-classic.waves-light .waves-ripple { - background: rgba(255, 255, 255, 0.4); + background: rgba(255, 255, 255, 0.4); } - .waves-notransition { - -webkit-transition: none !important; - -moz-transition: none !important; - -o-transition: none !important; - transition: none !important; + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + transition: none !important; } - .waves-button, .waves-circle { - -webkit-transform: translateZ(0); - -moz-transform: translateZ(0); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - transform: translateZ(0); - -webkit-mask-image: -webkit-radial-gradient(circle, #ffffff 100%, #000000 100%); -} - + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, #ffffff 100%, #000000 100%); +} .waves-button, .waves-button:hover, .waves-button:visited, .waves-button-input { - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - border: none; - outline: none; - color: inherit; - background-color: rgba(0, 0, 0, 0); - font-size: 1em; - line-height: 1em; - text-align: center; - text-decoration: none; - z-index: 1; -} - + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: none; + outline: none; + color: inherit; + background-color: rgba(0, 0, 0, 0); + font-size: 1em; + line-height: 1em; + text-align: center; + text-decoration: none; + z-index: 1; +} .waves-button { - padding: 0.85em 1.1em; - border-radius: 0.2em; + padding: 0.85em 1.1em; + border-radius: 0.2em; } - .waves-button-input { - margin: 0; - padding: 0.85em 1.1em; + margin: 0; + padding: 0.85em 1.1em; } - .waves-input-wrapper { - border-radius: 0.2em; - vertical-align: bottom; + border-radius: 0.2em; + vertical-align: bottom; } - .waves-input-wrapper.waves-button { - padding: 0; + padding: 0; } - .waves-input-wrapper .waves-button-input { - position: relative; - top: 0; - left: 0; - z-index: 1; + position: relative; + top: 0; + left: 0; + z-index: 1; } - .waves-circle { - text-align: center; - width: 2.5em; - height: 2.5em; - line-height: 2.5em; - border-radius: 50%; + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; } - .waves-float { - -webkit-mask-image: none; - -webkit-box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); - box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); - -webkit-transition: all 300ms; - -moz-transition: all 300ms; - -o-transition: all 300ms; - transition: all 300ms; -} - + -webkit-mask-image: none; + -webkit-box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + -webkit-transition: all 300ms; + -moz-transition: all 300ms; + -o-transition: all 300ms; + transition: all 300ms; +} .waves-float:active { - -webkit-box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); - box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); } - .waves-block { - display: block; -} \ No newline at end of file + display: block; +} diff --git a/waves.js b/waves.js index 135e392..d622919 100644 --- a/waves.js +++ b/waves.js @@ -1,6 +1,3 @@ -/** - * Created by teddyzhu on 16/4/12. - */ /*! * Waves v0.7.5 * http://fian.my.id/Waves @@ -9,9 +6,34 @@ * Released under the MIT license * https://github.com/fians/Waves/blob/master/LICENSE */ -require('./waves.css'); -module.exports = function (Vue) { - var toString = Object.prototype.toString; + +;(function(window, factory) { + 'use strict'; + + // AMD. Register as an anonymous module. Wrap in function so we have access + // to root via `this`. + if (typeof define === 'function' && define.amd) { + define([], function() { + return factory.apply(window); + }); + } + + // Node. Does not work with strict CommonJS, but only CommonJS-like + // environments that support module.exports, like Node. + else if (typeof exports === 'object') { + module.exports = factory.call(window); + } + + // Browser globals. + else { + window.Waves = factory.call(window); + } +})(typeof global === 'object' ? global : this, function() { + 'use strict'; + + var Waves = Waves || {}; + var $$ = document.querySelectorAll.bind(document); + var toString = Object.prototype.toString; var isTouchAvailable = 'ontouchstart' in window; @@ -24,10 +46,32 @@ module.exports = function (Vue) { return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView; } + function isObject(value) { + var type = typeof value; + return type === 'function' || type === 'object' && !!value; + } + + function isDOMNode(obj) { + return isObject(obj) && obj.nodeType > 0; + } + + function getWavesElements(nodes) { + var stringRepr = toString.call(nodes); + + if (stringRepr === '[object String]') { + return $$(nodes); + } else if (isObject(nodes) && /^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(stringRepr) && nodes.hasOwnProperty('length')) { + return nodes; + } else if (isDOMNode(nodes)) { + return [nodes]; + } + + return []; + } function offset(elem) { var docElem, win, - box = {top: 0, left: 0}, + box = { top: 0, left: 0 }, doc = elem && elem.ownerDocument; docElem = doc.documentElement; @@ -62,7 +106,7 @@ module.exports = function (Vue) { // Effect delay (check for scroll before showing effect) delay: 200, - show: function (e, element, velocity) { + show: function(e, element, velocity) { // Disable right click if (e.button === 2) { @@ -77,24 +121,24 @@ module.exports = function (Vue) { element.appendChild(ripple); // Get click coordinate and element width - var pos = offset(element); + var pos = offset(element); var relativeY = 0; var relativeX = 0; // Support for touch devices - if ('touches' in e && e.touches.length) { - relativeY = (e.touches[0].pageY - pos.top); - relativeX = (e.touches[0].pageX - pos.left); + if('touches' in e && e.touches.length) { + relativeY = (e.touches[0].pageY - pos.top); + relativeX = (e.touches[0].pageX - pos.left); } //Normal case else { - relativeY = (e.pageY - pos.top); - relativeX = (e.pageX - pos.left); + relativeY = (e.pageY - pos.top); + relativeX = (e.pageX - pos.left); } // Support for synthetic events relativeX = relativeX >= 0 ? relativeX : 0; relativeY = relativeY >= 0 ? relativeY : 0; - var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')'; + var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')'; var translate = 'translate(0,0)'; if (velocity) { @@ -128,14 +172,14 @@ module.exports = function (Vue) { var duration = e.type === 'mousemove' ? 2500 : Effect.duration; rippleStyle['-webkit-transition-duration'] = duration + 'ms'; - rippleStyle['-moz-transition-duration'] = duration + 'ms'; - rippleStyle['-o-transition-duration'] = duration + 'ms'; - rippleStyle['transition-duration'] = duration + 'ms'; + rippleStyle['-moz-transition-duration'] = duration + 'ms'; + rippleStyle['-o-transition-duration'] = duration + 'ms'; + rippleStyle['transition-duration'] = duration + 'ms'; ripple.setAttribute('style', convertStyle(rippleStyle)); }, - hide: function (e, element) { + hide: function(e, element) { element = element || this; var ripples = element.getElementsByClassName('waves-rippling'); @@ -143,6 +187,14 @@ module.exports = function (Vue) { for (var i = 0, len = ripples.length; i < len; i++) { removeRipple(e, element, ripples[i]); } + + if (isTouchAvailable) { + element.removeEventListener('touchend', Effect.hide); + element.removeEventListener('touchcancel', Effect.hide); + } + + element.removeEventListener('mouseup', Effect.hide); + element.removeEventListener('mouseleave', Effect.hide); } }; @@ -153,7 +205,7 @@ module.exports = function (Vue) { var TagWrapper = { // Wrap tag so it can perform the effect - input: function (element) { + input: function(element) { var parent = element.parentNode; @@ -163,7 +215,7 @@ module.exports = function (Vue) { } // Put element class and style to the specified parent - var wrapper = document.createElement('i'); + var wrapper = document.createElement('i'); wrapper.className = element.className + ' waves-input-wrapper'; element.className = 'waves-button-input'; @@ -172,8 +224,8 @@ module.exports = function (Vue) { wrapper.appendChild(element); // Apply element color and background color to wrapper - var elementStyle = window.getComputedStyle(element, null); - var color = elementStyle.color; + var elementStyle = window.getComputedStyle(element, null); + var color = elementStyle.color; var backgroundColor = elementStyle.backgroundColor; wrapper.setAttribute('style', 'color:' + color + ';background:' + backgroundColor); @@ -182,7 +234,7 @@ module.exports = function (Vue) { }, // Wrap tag so it can perform the effect - img: function (element) { + img: function(element) { var parent = element.parentNode; @@ -192,7 +244,7 @@ module.exports = function (Vue) { } // Put element as child - var wrapper = document.createElement('i'); + var wrapper = document.createElement('i'); parent.replaceChild(wrapper, element); wrapper.appendChild(element); @@ -214,7 +266,7 @@ module.exports = function (Vue) { var relativeX = ripple.getAttribute('data-x'); var relativeY = ripple.getAttribute('data-y'); - var scale = ripple.getAttribute('data-scale'); + var scale = ripple.getAttribute('data-scale'); var translate = ripple.getAttribute('data-translate'); // Get delay beetween mousedown and mouse leave @@ -232,7 +284,7 @@ module.exports = function (Vue) { // Fade out ripple after delay var duration = e.type === 'mousemove' ? 2500 : Effect.duration; - setTimeout(function () { + setTimeout(function() { var style = { top: relativeY + 'px', @@ -253,7 +305,7 @@ module.exports = function (Vue) { ripple.setAttribute('style', convertStyle(style)); - setTimeout(function () { + setTimeout(function() { try { el.removeChild(ripple); } catch (e) { @@ -276,7 +328,7 @@ module.exports = function (Vue) { * touchend, nor in the 500ms after touchend. */ touches: 0, - allowEvent: function (e) { + allowEvent: function(e) { var allow = true; @@ -286,7 +338,7 @@ module.exports = function (Vue) { return allow; }, - registerEvent: function (e) { + registerEvent: function(e) { var eType = e.type; if (eType === 'touchstart') { @@ -295,7 +347,7 @@ module.exports = function (Vue) { } else if (/^(touchend|touchcancel)$/.test(eType)) { - setTimeout(function () { + setTimeout(function() { if (TouchHandler.touches) { TouchHandler.touches -= 1; // pop after 500ms } @@ -316,13 +368,24 @@ module.exports = function (Vue) { return null; } - return e; + var element = null; + var target = e.target || e.srcElement; + + while (target.parentElement) { + if ( (!(target instanceof SVGElement)) && target.classList.contains('waves-effect')) { + element = target; + break; + } + target = target.parentElement; + } + + return element; } /** * Bubble the click and show effect if .waves-effect elem was found */ - function showEffect(e, element) { + function showEffect(e) { // Disable effect if element has "disabled" property on it // In some cases, the event is not triggered by the current element @@ -330,6 +393,8 @@ module.exports = function (Vue) { // return; // } + var element = getWavesEffectElement(e); + if (element !== null) { // Make it sure the element has either disabled property, disabled attribute or 'disabled' class @@ -348,7 +413,7 @@ module.exports = function (Vue) { Effect.show(e, element); }, Effect.delay); - var hideEffect = function (hideEvent) { + var hideEffect = function(hideEvent) { // if touch hasn't moved, and effect not yet started: start effect now if (timer) { @@ -360,20 +425,29 @@ module.exports = function (Vue) { hidden = true; Effect.hide(hideEvent, element); } + + removeListeners(); }; - var touchMove = function (moveEvent) { + var touchMove = function(moveEvent) { if (timer) { clearTimeout(timer); timer = null; } hideEffect(moveEvent); + + removeListeners(); }; element.addEventListener('touchmove', touchMove, false); element.addEventListener('touchend', hideEffect, false); element.addEventListener('touchcancel', hideEffect, false); + var removeListeners = function() { + element.removeEventListener('touchmove', touchMove); + element.removeEventListener('touchend', hideEffect); + element.removeEventListener('touchcancel', hideEffect); + }; } else { Effect.show(e, element); @@ -389,22 +463,49 @@ module.exports = function (Vue) { } } - Vue.directive("waves", { - name: 'waves', - version: '0.7.5', + Waves.init = function(options) { + var body = document.body; - bind: function () { + options = options || {}; - var classes = this.expression; + if ('duration' in options) { + Effect.duration = options.duration; + } - if (toString.call(classes) === '[object Array]') { - classes = classes.join(' '); - } + if ('delay' in options) { + Effect.delay = options.delay; + } - classes = classes ? ' ' + classes : ''; + if (isTouchAvailable) { + body.addEventListener('touchstart', showEffect, false); + body.addEventListener('touchcancel', TouchHandler.registerEvent, false); + body.addEventListener('touchend', TouchHandler.registerEvent, false); + } + + body.addEventListener('mousedown', showEffect, false); + }; - var element = this.el, tagName; + /** + * Attach Waves to dynamically loaded inputs, or add .waves-effect and other + * waves classes to a set of elements. Set drag to true if the ripple mouseover + * or skimming effect should be applied to the elements. + */ + Waves.attach = function(elements, classes) { + + elements = getWavesElements(elements); + + if (toString.call(classes) === '[object Array]') { + classes = classes.join(' '); + } + + classes = classes ? ' ' + classes : ''; + + var element, tagName; + + for (var i = 0, len = elements.length; i < len; i++) { + + element = elements[i]; tagName = element.tagName.toLowerCase(); if (['input', 'img'].indexOf(tagName) !== -1) { @@ -415,30 +516,84 @@ module.exports = function (Vue) { if (element.className.indexOf('waves-effect') === -1) { element.className += ' waves-effect' + classes; } + } + }; - this.show = function (e) { - return showEffect(e, element); - } - if (isTouchAvailable) { - element.addEventListener('touchstart', this.show, false); - element.addEventListener('touchcancel', TouchHandler.registerEvent, false); - element.addEventListener('touchend', TouchHandler.registerEvent, false); - } + /** + * Cause a ripple to appear in an element via code. + */ + Waves.ripple = function(elements, options) { + elements = getWavesElements(elements); + var elementsLen = elements.length; - element.addEventListener("mousedown", this.show, false); - }, + options = options || {}; + options.wait = options.wait || 0; + options.position = options.position || null; // default = centre of element - unbind: function () { - var mouseup = { - type: 'mouseup', + if (elementsLen) { + var element, pos, off, centre = {}, i = 0; + var mousedown = { + type: 'mousedown', button: 1 }; - Effect.hide(mouseup, this.el); + var hideRipple = function(mouseup, element) { + return function() { + Effect.hide(mouseup, element); + }; + }; + + for (; i < elementsLen; i++) { + element = elements[i]; + pos = options.position || { + x: element.clientWidth / 2, + y: element.clientHeight / 2 + }; + + off = offset(element); + centre.x = off.left + pos.x; + centre.y = off.top + pos.y; + + mousedown.pageX = centre.x; + mousedown.pageY = centre.y; + + Effect.show(mousedown, element); + + if (options.wait >= 0 && options.wait !== null) { + var mouseup = { + type: 'mouseup', + button: 1 + }; + + setTimeout(hideRipple(mouseup, element), options.wait); + } + } + } + }; + + /** + * Remove all ripples from an element. + */ + Waves.calm = function(elements) { + elements = getWavesElements(elements); + var mouseup = { + type: 'mouseup', + button: 1 + }; + for (var i = 0, len = elements.length; i < len; i++) { + Effect.hide(mouseup, elements[i]); } + }; + /** + * Deprecated API fallback + */ + Waves.displayEffect = function(options) { + console.error('Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect'); + Waves.init(options); + }; - }) -} \ No newline at end of file + return Waves; +}); diff --git a/webpack.config.babel.js b/webpack.config.babel.js new file mode 100644 index 0000000..a13cf8b --- /dev/null +++ b/webpack.config.babel.js @@ -0,0 +1,15 @@ +export default { + entry: './index.js', + output: { + path: './dist', + filename: 'vue-waves.js', + library: 'VueWaves', + libraryTarget: 'umd', + }, + module: { + loaders: [ + { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, + { test: /\.css$/, loader: "style-loader!css-loader" }, + ] + } +}