├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── bower.json
├── demo
├── demo-app.js
└── index.html
├── dist
├── css
│ ├── angular-flippy-fancy.css
│ ├── angular-flippy-fancy.min.css
│ ├── angular-flippy.css
│ └── angular-flippy.min.css
└── js
│ ├── angular-flippy.js
│ ├── angular-flippy.min.js
│ └── angular-flippy.min.js.map
├── gulpfile.js
├── js
└── src
│ └── flippy-directive.js
├── less
├── flippy-fancy.less
└── flippy.less
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esversion": 6,
3 |
4 | "bitwise": true,
5 | "curly": true,
6 | "es3": false,
7 | "eqnull": true,
8 | "forin": true,
9 | "freeze": true,
10 | "immed": true,
11 | "indent": 4,
12 | "latedef": "nofunc",
13 | "newcap": true,
14 | "noarg": true,
15 | "noempty": true,
16 | "nonbsp": true,
17 | "nonew": true,
18 | "plusplus": false,
19 | "undef": true,
20 | "unused": false,
21 | "strict": false,
22 | "maxdepth": 5,
23 |
24 | "asi": false,
25 | "boss": false,
26 | "camelcase": false,
27 | "debug": false,
28 | "eqeqeq": false,
29 | "evil": false,
30 | "expr": false,
31 | "funcscope": false,
32 | "globalstrict": false,
33 | "iterator": false,
34 | "lastsemic": false,
35 | "laxbreak": false,
36 | "laxcomma": false,
37 | "loopfunc": true,
38 | "maxcomplexity": false,
39 | "maxerr": false,
40 | "maxparams": false,
41 | "maxstatements": false,
42 | "moz": false,
43 | "multistr": false,
44 | "notypeof": false,
45 | "proto": false,
46 | "quotmark": false,
47 | "scripturl": false,
48 | "shadow": false,
49 | "sub": true,
50 | "supernew": false,
51 | "validthis": false,
52 | "noyield": false,
53 |
54 | "browser": true,
55 | "node": true,
56 |
57 | "globals": {
58 | "angular": false,
59 | "$": false,
60 | "ionic": false,
61 | "_": false
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Simon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-flippy
2 |
3 | AngularJS directive implementation with a CSS3 flip animation.
4 |
5 | With v2.0 you'll find more customization within the directive itself. You are free to hook into any events like `ng-click` to fire the flip event.
6 |
7 | ## Demo
8 |
9 | * Try the demo here: http://output.jsbin.com/panizijuka
10 | * Clone the repo and `gulp watch` to start the demo page locally
11 |
12 | ## Install
13 |
14 | * npm: `npm install angular-flippy`
15 | * bower: `bower install angular-flippy`
16 | * add *angular-flippy* to your `angular.module('your-webapp', ['angular-flippy', ...)` dependencies
17 |
18 | ## Flippy Directive Parameters
19 |
20 | ```html
21 |
27 |
28 | ```
29 | * `class`: fancy is an optional class to show some 3D-ness. (include `./css/flippy-fancy.min.css` for this exemplary style)
30 | * `flip`: events that trigger the first flip. will only trigger if flip state is in opposite flip state.
31 | * `flip-back`: events that trigger the flip back. will only trigger if flip state is in opposite flip state.
32 | * `duration`: the time it takes to flip in ms
33 | * `timing-function`: timing functions (see https://developer.mozilla.org/de/docs/Web/CSS/transition-timing-function)
34 |
35 | ## Events
36 |
37 | There are two types of events accepted for the `flip` (first flip) and `flip-back` (flip back):
38 | * Every [DOM event](https://en.wikipedia.org/wiki/DOM_events) e.g. click, mouseenter, mouseleave, dblclick, ...
39 | * `custom:XXX` where XXX is the name of the broadcast event
40 |
41 |
42 | ### Custom Events Example
43 | ```html
44 | // somewhere in your webapp
45 | function buttonClicked() {
46 | $rootScope.$broadcast('FLIP_EVENT_IN');
47 | }
48 |
49 | // your directive
50 |
55 |
56 | ```
57 |
58 | ## Contribute
59 |
60 | Just use `gulp watch` and hack away!
61 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-flippy",
3 | "version": "2.0.5",
4 | "description": "AngularJS directive implementation with a CSS3 flip animation",
5 | "homepage": "https://github.com/zwacky/angular-flippy",
6 | "license": "MIT",
7 | "main": [
8 | "./dist/js/angular-flippy.js",
9 | "./dist/css/angular-flippy.css",
10 | "./dist/css/angular-flippy-fancy.css"
11 | ],
12 | "ignore": [],
13 | "keywords": [
14 | "angular",
15 | "css3",
16 | "flip",
17 | "animation"
18 | ],
19 | "author": {
20 | "name": "Simon Wicki",
21 | "web": "https://github.com/zwacky"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/demo/demo-app.js:
--------------------------------------------------------------------------------
1 | angular.module('angular-flippy-demo', [
2 | 'angular-flippy'
3 | ]);
4 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
angular-flippy Demo Page
13 |
14 | Please refer to the README.md for instructions on how to use angular-flippy.
15 |
16 |
17 |
18 |
Item #{{$index+1}} (horizontal)
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
Item #{{$index+1}} (vertical)
38 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/dist/css/angular-flippy-fancy.css:
--------------------------------------------------------------------------------
1 | flippy.fancy {
2 | float: left;
3 | margin: 0 10px 10px 0;
4 | position: relative;
5 | font-size: .8em;
6 | cursor: pointer;
7 | width: 250px;
8 | height: 250px;
9 | }
10 | flippy.fancy img {
11 | height: 100%;
12 | width: 100%;
13 | }
14 | flippy.fancy flippy-front {
15 | float: none;
16 | position: absolute;
17 | top: 0;
18 | left: 0;
19 | z-index: 900;
20 | width: inherit;
21 | height: inherit;
22 | border: 1px solid #ccc;
23 | background: white;
24 | text-align: center;
25 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.9);
26 | }
27 | flippy.fancy flippy-front.flipped {
28 | border-color: #eee;
29 | /*background: #333;*/
30 | box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
31 | }
32 | flippy.fancy flippy-back {
33 | float: none;
34 | position: absolute;
35 | top: 0;
36 | left: 0;
37 | z-index: 800;
38 | width: inherit;
39 | height: inherit;
40 | border: 1px solid #ccc;
41 | background: white;
42 | text-align: center;
43 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.9);
44 | }
45 | flippy.fancy flippy-back.flipped {
46 | /*background: #80868d;*/
47 | box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
48 | }
49 |
--------------------------------------------------------------------------------
/dist/css/angular-flippy-fancy.min.css:
--------------------------------------------------------------------------------
1 | flippy.fancy{float:left;margin:0 10px 10px 0;position:relative;font-size:.8em;cursor:pointer;width:250px;height:250px}flippy.fancy img{height:100%;width:100%}flippy.fancy flippy-back,flippy.fancy flippy-front{float:none;position:absolute;top:0;left:0;width:inherit;height:inherit;background:#fff;text-align:center}flippy.fancy flippy-front{z-index:900;border:1px solid #ccc;box-shadow:0 1px 5px rgba(0,0,0,.9)}flippy.fancy flippy-front.flipped{border-color:#eee;box-shadow:0 15px 50px rgba(0,0,0,.2)}flippy.fancy flippy-back{z-index:800;border:1px solid #ccc;box-shadow:0 1px 5px rgba(0,0,0,.9)}flippy.fancy flippy-back.flipped{box-shadow:0 15px 50px rgba(0,0,0,.2)}
--------------------------------------------------------------------------------
/dist/css/angular-flippy.css:
--------------------------------------------------------------------------------
1 | flippy {
2 | float: left;
3 | -webkit-perspective: 600px;
4 | perspective: 600px;
5 | -ms-perspective: none;
6 | -moz-perspective: none;
7 | }
8 | flippy flippy-front,
9 | flippy flippy-back {
10 | position: absolute;
11 | width: inherit;
12 | height: inherit;
13 | -webkit-transform-style: preserve-3d;
14 | transform-style: preserve-3d;
15 | -webkit-backface-visibility: hidden;
16 | backface-visibility: hidden;
17 | }
18 | flippy flippy-front {
19 | z-index: 900;
20 | -webkit-transform: rotate3d(0, 0, 0, 0deg);
21 | transform: rotate3d(0, 0, 0, 0deg);
22 | -ms-transform: rotateY(0deg);
23 | }
24 | flippy flippy-back {
25 | z-index: 800;
26 | -webkit-transform: rotate3d(0, 1, 0, -180deg);
27 | transform: rotate3d(0, 1, 0, -180deg);
28 | -ms-transform: rotateY(180deg);
29 | }
30 | flippy.flipped flippy-front {
31 | z-index: 900;
32 | -webkit-transform: rotate3d(0, 1, 0, 180deg);
33 | transform: rotate3d(0, 1, 0, 180deg);
34 | -ms-transform: rotateY(180deg);
35 | }
36 | flippy.flipped flippy-back {
37 | z-index: 1000;
38 | -webkit-transform: rotate3d(0, 0, 0, 0deg);
39 | transform: rotate3d(0, 0, 0, 0deg);
40 | -ms-transform: rotateY(0deg);
41 | }
42 | flippy[vertical] flippy-front {
43 | z-index: 900;
44 | -webkit-transform: rotate3d(0, 0, 0, 0deg);
45 | transform: rotate3d(0, 0, 0, 0deg);
46 | -ms-transform: rotateY(0deg);
47 | }
48 | flippy[vertical] flippy-back {
49 | z-index: 800;
50 | -webkit-transform: rotate3d(1, 0, 0, -180deg) !important;
51 | transform: rotate3d(1, 0, 0, -180deg) !important;
52 | -ms-transform: rotateY(180deg);
53 | }
54 | flippy[vertical].flipped flippy-front {
55 | z-index: 900;
56 | -webkit-transform: rotate3d(1, 0, 0, 180deg) !important;
57 | transform: rotate3d(1, 0, 0, 180deg) !important;
58 | -ms-transform: rotateY(180deg);
59 | }
60 | flippy[vertical].flipped flippy-back {
61 | z-index: 1000;
62 | -webkit-transform: rotate3d(0, 0, 0, 0deg) !important;
63 | transform: rotate3d(0, 0, 0, 0deg) !important;
64 | }
65 |
--------------------------------------------------------------------------------
/dist/css/angular-flippy.min.css:
--------------------------------------------------------------------------------
1 | flippy{float:left;-webkit-perspective:600px;perspective:600px;-ms-perspective:none;-moz-perspective:none}flippy flippy-back,flippy flippy-front{position:absolute;width:inherit;height:inherit;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-backface-visibility:hidden;backface-visibility:hidden}flippy flippy-front{z-index:900;-webkit-transform:rotate3d(0,0,0,0deg);transform:rotate3d(0,0,0,0deg);-ms-transform:rotateY(0)}flippy flippy-back{z-index:800;-webkit-transform:rotate3d(0,1,0,-180deg);transform:rotate3d(0,1,0,-180deg);-ms-transform:rotateY(180deg)}flippy.flipped flippy-front{z-index:900;-webkit-transform:rotate3d(0,1,0,180deg);transform:rotate3d(0,1,0,180deg);-ms-transform:rotateY(180deg)}flippy.flipped flippy-back{z-index:1000;-webkit-transform:rotate3d(0,0,0,0deg);transform:rotate3d(0,0,0,0deg);-ms-transform:rotateY(0)}flippy[vertical] flippy-front{z-index:900;-webkit-transform:rotate3d(0,0,0,0deg);transform:rotate3d(0,0,0,0deg);-ms-transform:rotateY(0)}flippy[vertical] flippy-back{z-index:800;-webkit-transform:rotate3d(1,0,0,-180deg)!important;transform:rotate3d(1,0,0,-180deg)!important;-ms-transform:rotateY(180deg)}flippy[vertical].flipped flippy-front{z-index:900;-webkit-transform:rotate3d(1,0,0,180deg)!important;transform:rotate3d(1,0,0,180deg)!important;-ms-transform:rotateY(180deg)}flippy[vertical].flipped flippy-back{z-index:1000;-webkit-transform:rotate3d(0,0,0,0deg)!important;transform:rotate3d(0,0,0,0deg)!important}
--------------------------------------------------------------------------------
/dist/js/angular-flippy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * handles the behaviour of flipping card.
5 | */
6 | angular.module('angular-flippy', []).directive('flippy', function () {
7 | return {
8 | restrict: 'E',
9 | scope: {
10 | flip: '=',
11 | flipBack: '=',
12 | duration: '@',
13 | timingFunction: '@'
14 | },
15 | link: function link($scope, $elem, $attrs) {
16 |
17 | var CUSTOM_PREFIX = 'custom:';
18 | var state = {
19 | flipped: false
20 | };
21 | var options = {
22 | duration: 400,
23 | timingFunction: 'ease-in-out'
24 | };
25 |
26 | // assign new options
27 | angular.forEach(['duration', 'timingFunction'], function (item) {
28 | options[item] = $scope[item] ? $scope[item] : options[item];
29 | });
30 |
31 | angular.forEach({ flip: flip, flipBack: flipBack }, function (flipFunc, evt) {
32 | angular.forEach($scope[evt], function (eventName) {
33 | if (eventName.indexOf(CUSTOM_PREFIX) === -1) {
34 | // directly register event listener to avoid having to start off angular's digest cycle
35 | angular.element($elem)[0].addEventListener(eventName, flipFunc);
36 | } else {
37 | $scope.$on(eventName.substr(CUSTOM_PREFIX.length), flipFunc);
38 | }
39 | });
40 | });
41 |
42 | // set flip duration
43 | angular.forEach(['flippy-front', 'flippy-back'], function (name) {
44 | var el = $elem.find(name);
45 | if (el.length == 1) {
46 | angular.forEach(['', '-ms-', '-webkit-'], function (prefix) {
47 | angular.element(el[0]).css(prefix + 'transition', 'all ' + options.duration / 1000 + 's ' + options.timingFunction);
48 | });
49 | }
50 | });
51 |
52 | /**
53 | * flips the card.
54 | * will be ignored, if the state is already the same as the target state.
55 | *
56 | * @param boolean isBack
57 | */
58 | function _flip() {
59 | var isBack = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
60 |
61 | if (!isBack && !state.flipped || isBack && state.flipped) {
62 | // to avoid toggling it right back if flip-back is the same event
63 | setTimeout(function () {
64 | $elem.toggleClass('flipped');
65 | state.flipped = !state.flipped;
66 | }, 0);
67 | }
68 | }
69 |
70 | function flip() {
71 | _flip();
72 | }
73 |
74 | function flipBack() {
75 | _flip(true);
76 | }
77 | }
78 | };
79 | });
--------------------------------------------------------------------------------
/dist/js/angular-flippy.min.js:
--------------------------------------------------------------------------------
1 | "use strict";angular.module("angular-flippy",[]).directive("flippy",function(){return{restrict:"E",scope:{flip:"=",flipBack:"=",duration:"@",timingFunction:"@"},link:function(n,i,t){function a(){var n=arguments.length<=0||void 0===arguments[0]?!1:arguments[0];(!n&&!o.flipped||n&&o.flipped)&&setTimeout(function(){i.toggleClass("flipped"),o.flipped=!o.flipped},0)}function u(){a()}function e(){a(!0)}var l="custom:",o={flipped:!1},r={duration:400,timingFunction:"ease-in-out"};angular.forEach(["duration","timingFunction"],function(i){r[i]=n[i]?n[i]:r[i]}),angular.forEach({flip:u,flipBack:e},function(t,a){angular.forEach(n[a],function(a){-1===a.indexOf(l)?angular.element(i)[0].addEventListener(a,t):n.$on(a.substr(l.length),t)})}),angular.forEach(["flippy-front","flippy-back"],function(n){var t=i.find(n);1==t.length&&angular.forEach(["","-ms-","-webkit-"],function(n){angular.element(t[0]).css(n+"transition","all "+r.duration/1e3+"s "+r.timingFunction)})})}}});
2 | //# sourceMappingURL=angular-flippy.min.js.map
3 |
--------------------------------------------------------------------------------
/dist/js/angular-flippy.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["flippy-directive.js"],"names":["angular","module","directive","restrict","scope","flip","flipBack","duration","timingFunction","link","$scope","$elem","$attrs","_flip","isBack","arguments","length","undefined","state","flipped","setTimeout","toggleClass","CUSTOM_PREFIX","options","forEach","item","flipFunc","evt","eventName","indexOf","element","addEventListener","$on","substr","name","el","find","prefix","css"],"mappings":"AAAA,YAGAA,SAAQC,OAAO,qBACbC,UAAU,SAAU,WACpB,OACCC,SAAU,IACVC,OACCC,KAAM,IACNC,SAAU,IACVC,SAAU,IACVC,eAAgB,KAEjBC,KAAM,SAACC,EAAQC,EAAOC,GAAW,QA4CvBC,KACT,GADeC,GAAAC,UAAAC,QAAA,GAAAC,SAAAF,UAAA,IAAS,EAAAA,UAAA,KACjBD,IAAWI,EAAMC,SAAaL,GAAUI,EAAMC,UAEnDC,WAAW,WACVT,EAAMU,YAAY,WAClBH,EAAMC,SAAWD,EAAMC,SACrB,GAIL,QAASd,KACRQ,IAGD,QAASP,KACRO,GAAM,GAzDP,GAAMS,GAAgB,UAChBJ,GACLC,SAAS,GAEJI,GACLhB,SAAU,IACVC,eAAgB,cAReR,SAYxBwB,SAAS,WAAY,kBAAmB,SAACC,GAChDF,EAAQE,GAAQf,EAAQe,GAASf,EAAOe,GAAQF,EAAQE,KAGzDzB,QAAQwB,SAASnB,KAAMA,EAAMC,SAAUA,GAAW,SAACoB,EAAUC,GAC5D3B,QAAQwB,QAAQd,EAAOiB,GAAM,SAACC,GACY,KAArCA,EAAUC,QAAQP,GAErBtB,QAAQ8B,QAAQnB,GAAO,GAAGoB,iBAAiBH,EAAWF,GAEtDhB,EAAOsB,IAAIJ,EAAUK,OAAOX,EAAcN,QAASU,OAtBtB1B,QA4BxBwB,SAAS,eAAgB,eAAgB,SAACU,GACjD,GAAMC,GAAKxB,EAAMyB,KAAKF,EACL,IAAbC,EAAGnB,QACNhB,QAAQwB,SAAS,GAAI,OAAQ,YAAa,SAACa,GAC1CrC,QAAQ8B,QAAQK,EAAG,IAAIG,IAAID,EAAS,aAAc,OAASd,EAAQhB,SAAS,IAAO,KAAOgB,EAAQf","file":"angular-flippy.min.js","sourcesContent":["/**\n * handles the behaviour of flipping card.\n */\nangular.module('angular-flippy', [])\n\t.directive('flippy', () => {\n\t\treturn {\n\t\t\trestrict: 'E',\n\t\t\tscope: {\n\t\t\t\tflip: '=',\n\t\t\t\tflipBack: '=',\n\t\t\t\tduration: '@',\n\t\t\t\ttimingFunction: '@'\n\t\t\t},\n\t\t\tlink: ($scope, $elem, $attrs) => {\n\n\t\t\t\tconst CUSTOM_PREFIX = 'custom:';\n\t\t\t\tconst state = {\n\t\t\t\t\tflipped: false\n\t\t\t\t};\n\t\t\t\tconst options = {\n\t\t\t\t\tduration: 400,\n\t\t\t\t\ttimingFunction: 'ease-in-out'\n\t\t\t\t};\n\n\t\t\t\t// assign new options\n\t\t\t\tangular.forEach(['duration', 'timingFunction'], (item) => {\n\t\t\t\t\toptions[item] = ($scope[item]) ? $scope[item] : options[item];\n\t\t\t\t});\n\n\t\t\t\tangular.forEach({flip: flip, flipBack: flipBack}, (flipFunc, evt) => {\n\t\t\t\t\tangular.forEach($scope[evt], (eventName) => {\n\t\t\t\t\t\tif (eventName.indexOf(CUSTOM_PREFIX) === -1) {\n\t\t\t\t\t\t\t// directly register event listener to avoid having to start off angular's digest cycle\n\t\t\t\t\t\t\tangular.element($elem)[0].addEventListener(eventName, flipFunc);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$scope.$on(eventName.substr(CUSTOM_PREFIX.length), flipFunc);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// set flip duration\n\t\t\t\tangular.forEach(['flippy-front', 'flippy-back'], (name) => {\n\t\t\t\t\tconst el = $elem.find(name);\n\t\t\t\t\tif (el.length == 1) {\n\t\t\t\t\t\tangular.forEach(['', '-ms-', '-webkit-'], (prefix) => {\n\t\t\t\t\t\t\tangular.element(el[0]).css(prefix + 'transition', 'all ' + options.duration/1000 + 's ' + options.timingFunction);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\n\t\t\t\t/**\n\t\t\t\t * flips the card.\n\t\t\t\t * will be ignored, if the state is already the same as the target state.\n\t\t\t\t *\n\t\t\t\t * @param boolean isBack\n\t\t\t\t */\n\t\t\t\tfunction _flip(isBack = false) {\n\t\t\t\t\tif ((!isBack && !state.flipped) || (isBack && state.flipped)) {\n\t\t\t\t\t\t// to avoid toggling it right back if flip-back is the same event\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t$elem.toggleClass('flipped');\n\t\t\t\t\t\t\tstate.flipped = !state.flipped;\n\t\t\t\t\t\t}, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfunction flip() {\n\t\t\t\t\t_flip();\n\t\t\t\t}\n\n\t\t\t\tfunction flipBack() {\n\t\t\t\t\t_flip(true);\n\t\t\t\t}\n\n\t\t\t}\n\t\t};\n\t});\n"],"sourceRoot":"/source/"}
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var plugins = require('gulp-load-plugins')();
3 | var del = require('del');
4 | var merge = require('merge-stream');
5 | var runSequence = require('run-sequence');
6 | var browserSync = require('browser-sync').create();
7 | var history = require('connect-history-api-fallback');
8 |
9 | var paths = {
10 | less: ['./less/*.less'],
11 | js: ['./js/src/**/*.js'],
12 | dist: {
13 | css: './dist/css/',
14 | js: './dist/js/',
15 | }
16 | };
17 |
18 |
19 |
20 | /**
21 | * removes css- and js-dist folder.
22 | */
23 | gulp.task('clean', function() {
24 | return del(['./dist']);
25 | });
26 |
27 | /**
28 | * compiles less files into css.
29 | */
30 | gulp.task('style', function() {
31 | var streams = {};
32 | streams.flippy = gulp.src('./less/flippy.less')
33 | .pipe(plugins.less())
34 | .pipe(plugins.autoprefixer(['> 1%','last 3 versions']))
35 | .pipe(plugins.concat('angular-flippy.css'))
36 | .pipe(gulp.dest(paths.dist.css))
37 | .pipe(plugins.minifyCss())
38 | .pipe(plugins.concat('angular-flippy.min.css'))
39 | .pipe(gulp.dest(paths.dist.css));
40 |
41 | // fancy
42 | streams.flippyFancy = gulp.src('./less/flippy-fancy.less')
43 | .pipe(plugins.less())
44 | .pipe(plugins.autoprefixer(['> 1%','last 3 versions']))
45 | .pipe(plugins.concat('angular-flippy-fancy.css'))
46 | .pipe(gulp.dest(paths.dist.css))
47 | .pipe(plugins.minifyCss())
48 | .pipe(plugins.concat('angular-flippy-fancy.min.css'))
49 | .pipe(gulp.dest(paths.dist.css));
50 |
51 | return merge(streams.flippy, streams.flippyFancy);
52 | });
53 |
54 | gulp.task('js', ['lint'], function() {
55 | return gulp.src(paths.js)
56 | .pipe(plugins.sourcemaps.init())
57 | .pipe(plugins.babel({
58 | presets: ['es2015']
59 | }))
60 | .pipe(plugins.ngAnnotate())
61 | .pipe(plugins.concat('angular-flippy.js'))
62 | .pipe(gulp.dest(paths.dist.js))
63 | .pipe(plugins.uglify())
64 | .pipe(plugins.concat('angular-flippy.min.js'))
65 | .pipe(plugins.sourcemaps.write('.'))
66 | .pipe(gulp.dest(paths.dist.js));
67 | });
68 |
69 | gulp.task('lint', function() {
70 | return gulp.src(paths.js)
71 | .pipe(plugins.jshint())
72 | .pipe(plugins.jshint.reporter('jshint-stylish'))
73 | .pipe(plugins.jshint.reporter('fail'));
74 | })
75 |
76 | gulp.task('watch', ['build'], function() {
77 | gulp.watch(paths.less, ['watch-style']);
78 | gulp.watch(paths.js, ['watch-js']);
79 |
80 | browserSync.init({
81 | server: {
82 | baseDir: '',
83 | middleware: [ history() ]
84 | },
85 | startPath: '/demo/'
86 | });
87 | });
88 |
89 | gulp.task('_browser-reload', function(cb) {
90 | browserSync.reload();
91 | cb();
92 | });
93 |
94 | gulp.task('watch-style', function(cb) {
95 | return runSequence(['style'], ['_browser-reload'], cb);
96 | });
97 |
98 | gulp.task('watch-js', function(cb) {
99 | return runSequence(['js'], ['_browser-reload'], cb);
100 | });
101 |
102 |
103 | gulp.task('build', function() {
104 | return runSequence(['clean'], ['style', 'js']);
105 | });
106 | gulp.task('default', ['build']);
107 |
--------------------------------------------------------------------------------
/js/src/flippy-directive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * handles the behaviour of flipping card.
3 | */
4 | angular.module('angular-flippy', [])
5 | .directive('flippy', () => {
6 | return {
7 | restrict: 'E',
8 | scope: {
9 | flip: '=',
10 | flipBack: '=',
11 | duration: '@',
12 | timingFunction: '@'
13 | },
14 | link: ($scope, $elem, $attrs) => {
15 |
16 | const CUSTOM_PREFIX = 'custom:';
17 | const state = {
18 | flipped: false
19 | };
20 | const options = {
21 | duration: 400,
22 | timingFunction: 'ease-in-out'
23 | };
24 |
25 | // assign new options
26 | angular.forEach(['duration', 'timingFunction'], (item) => {
27 | options[item] = ($scope[item]) ? $scope[item] : options[item];
28 | });
29 |
30 | angular.forEach({flip: flip, flipBack: flipBack}, (flipFunc, evt) => {
31 | angular.forEach($scope[evt], (eventName) => {
32 | if (eventName.indexOf(CUSTOM_PREFIX) === -1) {
33 | // directly register event listener to avoid having to start off angular's digest cycle
34 | angular.element($elem)[0].addEventListener(eventName, flipFunc);
35 | } else {
36 | $scope.$on(eventName.substr(CUSTOM_PREFIX.length), flipFunc);
37 | }
38 | });
39 | });
40 |
41 | // set flip duration
42 | angular.forEach(['flippy-front', 'flippy-back'], (name) => {
43 | const el = $elem.find(name);
44 | if (el.length == 1) {
45 | angular.forEach(['', '-ms-', '-webkit-'], (prefix) => {
46 | angular.element(el[0]).css(prefix + 'transition', 'all ' + options.duration/1000 + 's ' + options.timingFunction);
47 | });
48 | }
49 | });
50 |
51 |
52 | /**
53 | * flips the card.
54 | * will be ignored, if the state is already the same as the target state.
55 | *
56 | * @param boolean isBack
57 | */
58 | function _flip(isBack = false) {
59 | if ((!isBack && !state.flipped) || (isBack && state.flipped)) {
60 | // to avoid toggling it right back if flip-back is the same event
61 | setTimeout(() => {
62 | $elem.toggleClass('flipped');
63 | state.flipped = !state.flipped;
64 | }, 0);
65 | }
66 | }
67 |
68 | function flip() {
69 | _flip();
70 | }
71 |
72 | function flipBack() {
73 | _flip(true);
74 | }
75 |
76 | }
77 | };
78 | });
79 |
--------------------------------------------------------------------------------
/less/flippy-fancy.less:
--------------------------------------------------------------------------------
1 | @card-width: 250px;
2 | @card-height: @card-width;
3 |
4 | flippy {
5 | &.fancy {
6 | float: left;
7 | margin: 0 10px 10px 0;
8 | position: relative;
9 | font-size: .8em;
10 | cursor: pointer;
11 | width: @card-width;
12 | height: @card-height;
13 |
14 | img {
15 | height: 100%;
16 | width: 100%;
17 | }
18 |
19 | flippy-front {
20 | float: none;
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | z-index: 900;
25 | width: inherit;
26 | height: inherit;
27 | border: 1px solid #ccc;
28 | background: white;
29 | text-align: center;
30 | box-shadow: 0 1px 5px rgba(0,0,0,0.9);
31 |
32 | &.flipped {
33 | border-color: #eee;
34 | /*background: #333;*/
35 | box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
36 | }
37 | }
38 |
39 | flippy-back {
40 | float: none;
41 | position: absolute;
42 | top: 0;
43 | left: 0;
44 | z-index: 800;
45 | width: inherit;
46 | height: inherit;
47 | border: 1px solid #ccc;
48 | background: white;
49 | text-align: center;
50 | box-shadow: 0 1px 5px rgba(0,0,0,0.9);
51 |
52 | &.flipped {
53 | /*background: #80868d;*/
54 | box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/less/flippy.less:
--------------------------------------------------------------------------------
1 | flippy {
2 | float: left;
3 | perspective: 600px;
4 | -ms-perspective: none;
5 | -moz-perspective: none;
6 | flippy-front, flippy-back {
7 | position: absolute;
8 | width: inherit;
9 | height: inherit;
10 | transform-style: preserve-3d;
11 | backface-visibility: hidden;
12 | }
13 | flippy-front {
14 | z-index: 900;
15 | transform: rotate3d( 0, 0, 0, 0deg);
16 | -ms-transform: rotateY(0deg);
17 | // will be set in the directive
18 | // transition: all @flip-duration ease-in-out;
19 | }
20 | flippy-back {
21 | z-index: 800;
22 | transform: rotate3d( 0, 1, 0, -180deg);
23 | -ms-transform: rotateY(180deg);
24 | // will be set in the directive
25 | // transition: all @flip-duration ease-in-out;
26 | }
27 | &.flipped {
28 | flippy-front {
29 | z-index: 900;
30 | transform: rotate3d( 0, 1, 0, 180deg);
31 | -ms-transform: rotateY(180deg);
32 | }
33 | flippy-back {
34 | z-index: 1000;
35 | transform: rotate3d( 0, 0, 0, 0deg);
36 | -ms-transform: rotateY(0deg);
37 | }
38 | }
39 | }
40 |
41 | flippy[vertical] {
42 | flippy-front {
43 | z-index: 900;
44 | -webkit-transform: rotate3d(0, 0, 0, 0deg);
45 | transform: rotate3d(0, 0, 0, 0deg);
46 | -ms-transform: rotateY(0deg);
47 | }
48 | flippy-back {
49 | z-index: 800;
50 | -webkit-transform: rotate3d(1, 0, 0, -180deg)!important;
51 | transform: rotate3d(1, 0, 0, -180deg)!important;
52 | -ms-transform: rotateY(180deg);
53 | }
54 | &.flipped {
55 | flippy-front {
56 | z-index: 900;
57 | -webkit-transform: rotate3d(1, 0, 0, 180deg)!important;
58 | transform: rotate3d(1, 0, 0, 180deg)!important;
59 | -ms-transform: rotateY(180deg);
60 | }
61 | flippy-back {
62 | z-index: 1000;
63 | -webkit-transform: rotate3d(0, 0, 0, 0deg)!important;
64 | transform: rotate3d(0, 0, 0, 0deg)!important;
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-flippy",
3 | "version": "2.1.1",
4 | "description": "AngularJS directive implementation with a CSS3 flip animation.",
5 | "main": "dist/js/angular-flippy.min.js",
6 | "scripts": {},
7 | "repository": {
8 | "type": "git",
9 | "url": "git://github.com/zwacky/angular-flippy.git"
10 | },
11 | "author": "Simon Wicki ",
12 | "license": "MIT",
13 | "devDependencies": {
14 | "angular": "^1.5.0",
15 | "babel-preset-es2015": "^6.3.13",
16 | "bootstrap": "^3.3.6",
17 | "browser-sync": "^2.11.1",
18 | "connect-history-api-fallback": "^1.1.0",
19 | "del": "^2.2.0",
20 | "gulp": "^3.9.0",
21 | "gulp-autoprefixer": "^3.1.0",
22 | "gulp-babel": "^6.1.2",
23 | "gulp-concat": "^2.6.0",
24 | "gulp-conventional-changelog": "^0.7.0",
25 | "gulp-jshint": "^2.0.0",
26 | "gulp-less": "^3.0.5",
27 | "gulp-livereload": "^3.8.1",
28 | "gulp-load-plugins": "^1.2.0",
29 | "gulp-minify-css": "^1.2.3",
30 | "gulp-ng-annotate": "^1.1.0",
31 | "gulp-purifycss": "^0.2.0",
32 | "gulp-sourcemaps": "^1.6.0",
33 | "gulp-uglify": "^1.5.1",
34 | "jshint": "^2.9.1",
35 | "jshint-stylish": "^2.1.0",
36 | "merge-stream": "^1.0.0",
37 | "run-sequence": "^1.1.5"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------