├── README.md
├── demo
├── dialog.html
├── prompt.html
└── toaste.html
├── gulpfile.js
├── js
├── animate-rippler.js
├── animate.js
├── effects.js
└── refresh.js
├── lib
├── ajax.js
├── data.js
├── event.js
├── os.js
├── raf.js
├── touch.js
└── zepto.js
├── package.json
└── styles
└── prompt.css
/README.md:
--------------------------------------------------------------------------------
1 | MaterialUI
2 | ==========
3 |
4 | Google Material Design UI.
5 |
6 | Depend on Zepto.js.
7 |
8 | Make your webapp more like native app.
9 |
10 | Mobile Only!
11 |
12 | Lightweight!
13 |
14 | High Performance!
15 |
16 | ## Some Implementation
17 |
18 | * [material-refresh](https://github.com/lightningtgc/material-refresh)
19 |
--------------------------------------------------------------------------------
/demo/dialog.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightningtgc/MaterialUI/00141d8eb4f3ac9afe5c124b6d4b0809348e779f/demo/dialog.html
--------------------------------------------------------------------------------
/demo/prompt.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightningtgc/MaterialUI/00141d8eb4f3ac9afe5c124b6d4b0809348e779f/demo/prompt.html
--------------------------------------------------------------------------------
/demo/toaste.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightningtgc/MaterialUI/00141d8eb4f3ac9afe5c124b6d4b0809348e779f/demo/toaste.html
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var gulp = require('gulp');
3 | var source = require('vinyl-source-stream');
4 |
5 | gulp.task('browserify', function() {
6 | return browserify('./src/javascript/app.js').bundle()
7 | // vinyl-source-stream makes the bundle compatible with gulp
8 | .pipe(source('bundle.js')) // Desired filename
9 | // Output the file
10 | .pipe(gulp.dest('./build/'));
11 | });
12 |
13 |
--------------------------------------------------------------------------------
/js/animate-rippler.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightningtgc/MaterialUI/00141d8eb4f3ac9afe5c124b6d4b0809348e779f/js/animate-rippler.js
--------------------------------------------------------------------------------
/js/animate.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | var $ripple = require("./animate-rippler.js");
3 | var $raf = require("../lib/raf.js");
4 |
5 | function MaterialEffects($ripple, $raf){
6 |
7 | return {
8 | inkRipple: animateInkRipple
9 | };
10 |
11 | /**
12 | * Use the canvas animator to render the ripple effect(s).
13 | */
14 | function animateInkRipple (canvas, options) {
15 | return new $ripple(canvas, options);
16 | }
17 |
18 | };
19 |
20 | function MaterialRippleDirective(){
21 | return {
22 | compile: compileWithCanvas
23 | };
24 | /**
25 | * Use Javascript and Canvas to render ripple effects
26 | *
27 | * Note: attribute start="" has two (2) options: `center` || `pointer`; which
28 | * defines the start of the ripple center.
29 | *
30 | * @param element
31 | * @returns {Function}
32 | */
33 | function compileWithCanvas( element, attrs ) {
34 | var RIGHT_BUTTON = 2;
35 | var options = calculateOptions(element, attrs);
36 | var tag =
37 | '';
41 |
42 | element.replaceWith(
43 | angular.element( $interpolate(tag)(options) )
44 | );
45 |
46 | return function linkCanvas( scope, element ){
47 |
48 | var ripple, watchMouse,
49 | parent = element.parent(),
50 | makeRipple = $throttle({
51 | start : function() {
52 | ripple = ripple || MaterialEffects.inkRipple( element[0], options );
53 | watchMouse = watchMouse || buildMouseWatcher(parent, makeRipple);
54 |
55 | // Ripples start with left mouseDowns (or taps)
56 | parent.on('mousedown', makeRipple);
57 | },
58 | throttle : function(e, done) {
59 | if ( effectAllowed() )
60 | {
61 | switch(e.type)
62 | {
63 | case 'mousedown' :
64 | // If not right- or ctrl-click...
65 | if (!e.ctrlKey && (e.button !== RIGHT_BUTTON))
66 | {
67 | watchMouse(true);
68 | ripple.createAt( options.forceToCenter ? null : localToCanvas(e) );
69 | }
70 | break;
71 |
72 | default:
73 | watchMouse(false);
74 |
75 | // Draw of each wave/ripple in the ink only occurs
76 | // on mouseup/mouseleave
77 |
78 | ripple.draw( done );
79 | break;
80 | }
81 | } else {
82 | done();
83 | }
84 | },
85 | end : function() {
86 | watchMouse(false);
87 | }
88 | })();
89 |
90 |
91 |
92 | };
93 |
94 | });
95 |
--------------------------------------------------------------------------------
/js/effects.js:
--------------------------------------------------------------------------------
1 | angular.module('material.animations', ['ngAnimateStylers', 'ngAnimateSequence', 'ngAnimate', 'material.services'])
2 | .service('materialEffects', [ '$animateSequence', '$ripple', '$rootElement', '$position', '$$rAF', MaterialEffects])
3 | .directive('materialRipple', ['materialEffects', '$interpolate', '$throttle', MaterialRippleDirective]);
4 |
5 | /**
6 | * This service provides animation features for various Material Design effects:
7 | *
8 | * 1) ink stretchBars,
9 | * 2) ink ripples,
10 | * 3) popIn animations
11 | * 4) popOuts animations
12 | *
13 | * @constructor
14 | */
15 | function MaterialEffects($animateSequence, $ripple, $rootElement, $position, $$rAF) {
16 |
17 | var styler = angular.isDefined( $rootElement[0].animate ) ? 'webAnimations' :
18 | angular.isDefined( window['TweenMax'] || window['TweenLite'] ) ? 'gsap' :
19 | angular.isDefined( window['jQuery'] ) ? 'jQuery' : 'default';
20 |
21 | // Publish API for effects...
22 |
23 | return {
24 | inkRipple: animateInkRipple,
25 | inkBar: animateInkBar,
26 | popIn: popIn,
27 | popOut: popOut
28 | };
29 |
30 | // **********************************************************
31 | // API Methods
32 | // **********************************************************
33 |
34 | /**
35 | * Use the canvas animator to render the ripple effect(s).
36 | */
37 | function animateInkRipple( canvas, options )
38 | {
39 | return new $ripple(canvas, options);
40 | }
41 |
42 |
43 | /**
44 | * Make instance of a reusable sequence and
45 | * auto-run the sequence on the element (if defined)
46 | */
47 | function animateInkBar(element, styles, duration ) {
48 | var animate = $animateSequence({ styler: styler }).animate,
49 | sequence = animate( {}, styles, safeDuration(duration || 350) );
50 |
51 | return angular.isDefined(element) ? sequence.run(element) : sequence;
52 | }
53 |
54 |
55 | /**
56 | *
57 | */
58 | function popIn(element, parentElement, clickElement) {
59 | var startPos;
60 | var endPos = $position.positionElements(parentElement, element, 'center');
61 | if (clickElement) {
62 | var dialogPos = $position.position(element);
63 | var clickPos = $position.offset(clickElement);
64 | startPos = {
65 | left: clickPos.left - dialogPos.width / 2,
66 | top: clickPos.top - dialogPos.height / 2
67 | };
68 | } else {
69 | startPos = endPos;
70 | }
71 |
72 | // TODO once ngAnimateSequence bugs are fixed, this can be switched to use that
73 | element.css({
74 | '-webkit-transform': translateString(startPos.left, startPos.top, 0) + ' scale(0.2)',
75 | opacity: 0
76 | });
77 | $$rAF(function() {
78 | element.addClass('dialog-changing');
79 | $$rAF(function() {
80 | element.css({
81 | '-webkit-transform': translateString(endPos.left, endPos.top, 0) + ' scale(1.0)',
82 | opacity: 1
83 | });
84 | });
85 | });
86 | }
87 |
88 | /**
89 | *
90 | *
91 | */
92 | function popOut(element, parentElement) {
93 | var endPos = $position.positionElements(parentElement, element, 'bottom-center');
94 |
95 | endPos.top -= element.prop('offsetHeight') / 2;
96 |
97 | var runner = $animateSequence({ styler: styler })
98 | .addClass('dialog-changing')
99 | .then(function() {
100 | element.css({
101 | '-webkit-transform': translateString(endPos.left, endPos.top, 0) + ' scale(0.5)',
102 | opacity: 0
103 | });
104 | });
105 |
106 | return runner.run(element);
107 | }
108 |
109 |
110 | // **********************************************************
111 | // Utility Methods
112 | // **********************************************************
113 |
114 |
115 | function translateString(x, y, z) {
116 | return 'translate3d(' + x + 'px,' + y + 'px,' + z + 'px)';
117 | }
118 |
119 |
120 | /**
121 | * Support values such as 0.65 secs or 650 msecs
122 | */
123 | function safeDuration(value) {
124 | var duration = isNaN(value) ? 0 : Number(value);
125 | return (duration < 1.0) ? (duration * 1000) : duration;
126 | }
127 |
128 | /**
129 | * Convert all values to decimal;
130 | * eg 150 msecs -> 0.15sec
131 | */
132 | function safeVelocity(value) {
133 | var duration = isNaN(value) ? 0 : Number(value);
134 | return (duration > 100) ? (duration / 1000) :
135 | (duration > 10 ) ? (duration / 100) :
136 | (duration > 1 ) ? (duration / 10) : duration;
137 | }
138 |
139 | }
140 |
141 | /**
142 | * Directive
143 | */
144 | function MaterialRippleDirective(materialEffects, $interpolate, $throttle) {
145 | return {
146 | restrict: 'E',
147 | compile: compileWithCanvas
148 | };
149 |
150 | /**
151 | * Use Javascript and Canvas to render ripple effects
152 | *
153 | * Note: attribute start="" has two (2) options: `center` || `pointer`; which
154 | * defines the start of the ripple center.
155 | *
156 | * @param element
157 | * @returns {Function}
158 | */
159 | function compileWithCanvas( element, attrs ) {
160 | var RIGHT_BUTTON = 2;
161 | var options = calculateOptions(element, attrs);
162 | var tag =
163 | '';
167 |
168 | element.replaceWith(
169 | angular.element( $interpolate(tag)(options) )
170 | );
171 |
172 | return function linkCanvas( scope, element ){
173 |
174 | var ripple, watchMouse,
175 | parent = element.parent(),
176 | makeRipple = $throttle({
177 | start : function() {
178 | ripple = ripple || materialEffects.inkRipple( element[0], options );
179 | watchMouse = watchMouse || buildMouseWatcher(parent, makeRipple);
180 |
181 | // Ripples start with left mouseDowns (or taps)
182 | parent.on('mousedown', makeRipple);
183 | },
184 | throttle : function(e, done) {
185 | if ( effectAllowed() )
186 | {
187 | switch(e.type)
188 | {
189 | case 'mousedown' :
190 | // If not right- or ctrl-click...
191 | if (!e.ctrlKey && (e.button !== RIGHT_BUTTON))
192 | {
193 | watchMouse(true);
194 | ripple.createAt( options.forceToCenter ? null : localToCanvas(e) );
195 | }
196 | break;
197 |
198 | default:
199 | watchMouse(false);
200 |
201 | // Draw of each wave/ripple in the ink only occurs
202 | // on mouseup/mouseleave
203 |
204 | ripple.draw( done );
205 | break;
206 | }
207 | } else {
208 | done();
209 | }
210 | },
211 | end : function() {
212 | watchMouse(false);
213 | }
214 | })();
215 |
216 |
217 | // **********************************************************
218 | // Utility Methods
219 | // **********************************************************
220 |
221 | /**
222 | * If the ripple canvas been removed from the DOM, then
223 | * remove the `mousedown` listener
224 | *
225 | * @returns {*|boolean}
226 | */
227 | function effectAllowed() {
228 | var allowed = isInkEnabled( element.scope() ) && angular.isDefined( element.parent()[0] );
229 | if ( !allowed ) {
230 | parent.off('mousedown', makeRipple);
231 | }
232 | return allowed;
233 |
234 |
235 | /**
236 | * Check scope chain for `inkEnabled` or `disabled` flags...
237 | */
238 | function isInkEnabled(scope) {
239 | return angular.isUndefined(scope) ? true :
240 | angular.isDefined(scope.disabled) ? !scope.disabled :
241 | angular.isDefined(scope.inkEnabled) ? scope.inkEnabled : true;
242 | }
243 |
244 | }
245 |
246 | /**
247 | * Build mouse event listeners for the specified element
248 | * @param element Angular element that will listen for bubbling mouseEvents
249 | * @param handlerFn Function to be invoked with the mouse event
250 | * @returns {Function}
251 | */
252 | function buildMouseWatcher(element, handlerFn) {
253 | // Return function to easily toggle on/off listeners
254 | return function watchMouse(active) {
255 | angular.forEach("mouseup,mouseleave".split(","), function(eventType) {
256 | var fn = active ? element.on : element.off;
257 | fn.apply(element, [eventType, handlerFn]);
258 | });
259 | }
260 | }
261 | /**
262 | * Convert the mouse down coordinates from `parent` relative
263 | * to `canvas` relative; needed since the event listener is on
264 | * the parent [e.g. tab element]
265 | */
266 | function localToCanvas(e)
267 | {
268 | var canvas = element[0].getBoundingClientRect();
269 |
270 | return {
271 | x : e.clientX - canvas.left,
272 | y : e.clientY - canvas.top
273 | };
274 | }
275 |
276 | }
277 |
278 | function calculateOptions(element, attrs)
279 | {
280 | return angular.extend( getBounds(element), {
281 | classList : (attrs.class || ""),
282 | forceToCenter : (attrs.start == "center"),
283 | initialOpacity : getFloatValue( attrs, "initialOpacity" ),
284 | opacityDecayVelocity : getFloatValue( attrs, "opacityDecayVelocity" )
285 | });
286 |
287 | function getBounds(element) {
288 | var node = element[0];
289 | var styles = node.ownerDocument.defaultView.getComputedStyle( node, null ) || { };
290 |
291 | return {
292 | left : (styles.left == "auto" || !styles.left) ? "0px" : styles.left,
293 | top : (styles.top == "auto" || !styles.top) ? "0px" : styles.top,
294 | width : getValue( styles, "width" ),
295 | height : getValue( styles, "height" )
296 | };
297 | }
298 |
299 | function getFloatValue( map, key, defaultVal )
300 | {
301 | return angular.isDefined( map[key] ) ? +map[key] : defaultVal;
302 | }
303 |
304 | function getValue( map, key, defaultVal )
305 | {
306 | var val = map[key];
307 | return (angular.isDefined( val ) && (val !== "")) ? map[key] : defaultVal;
308 | }
309 | }
310 |
311 | }
312 |
313 |
314 |
315 | }
316 |
--------------------------------------------------------------------------------
/js/refresh.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/ajax.js:
--------------------------------------------------------------------------------
1 | define(['./zepto'], function(){
2 | // Zepto.js
3 | // (c) 2010-2014 Thomas Fuchs
4 | // Zepto.js may be freely distributed under the MIT license.
5 |
6 | ;(function($){
7 | var jsonpID = 0,
8 | document = window.document,
9 | key,
10 | name,
11 | rscript = /