From 425f043fea74f1dffbba4cb071263c72390f8543 Mon Sep 17 00:00:00 2001 From: Valentin Shevko Date: Wed, 18 Sep 2013 00:05:23 +0300 Subject: [PATCH 001/159] fix bower components path All bower package contents are installed in the 'bower_components' directory by default, but everywhere in the project is used 'components' directory. --- .bowerrc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .bowerrc diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..5c1bf29 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,4 @@ +{ + "directory": "components", + "json": "bower.json" +} From dd972a965b273ffe6af97408a530081d214a6550 Mon Sep 17 00:00:00 2001 From: Valentin Shevko Date: Wed, 18 Sep 2013 00:18:44 +0300 Subject: [PATCH 002/159] fix animations flicker in some case --- src/css/angular-carousel.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/css/angular-carousel.css b/src/css/angular-carousel.css index 66a8976..3637e37 100644 --- a/src/css/angular-carousel.css +++ b/src/css/angular-carousel.css @@ -23,6 +23,8 @@ ul.rn-carousel-slides li { height: 100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; } .rn-carousel-animate { -webkit-transition: -webkit-transform .1s ease-out; From 7c56fe172c396b7276d3e20d979047d83d9a0566 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 5 Jan 2014 00:16:59 +0100 Subject: [PATCH 003/159] refactor: complete rewrite --- .bowerrc | 3 + .gitignore | 3 +- Gruntfile.js | 99 ++- README.md | 33 +- TODO | 34 + bower.json | 16 +- component.json | 18 - demo/dynamic.html | 120 --- demo/flickr-full/index.html | 4 +- demo/img/grumpy.jpg | Bin 0 -> 40046 bytes demo/img/sophie.jpeg | Bin 0 -> 4373 bytes demo/infinite.html | 121 --- demo/infinite2.html | 121 --- dist/angular-carousel.css | 27 + dist/angular-carousel.js | 971 +++++++++---------------- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 +- dist/angular-mobile.js | 2 +- index.html | 415 +++++------ package.json | 20 +- src/angular-carousel.js | 12 +- src/css/angular-carousel.css | 64 +- src/directives/rn-carousel-infinite.js | 23 - src/directives/rn-carousel.js | 726 +++++++++--------- src/directives/sliceFilter.js | 12 + src/services/CollectionManager.js | 203 ------ test.html | 112 --- test/karma.conf.js | 130 ++-- test/unit/angular-carousel.js | 27 +- test/unit/collectionManager.js | 227 ------ 30 files changed, 1130 insertions(+), 2419 deletions(-) create mode 100644 .bowerrc create mode 100644 TODO delete mode 100644 component.json delete mode 100644 demo/dynamic.html create mode 100644 demo/img/grumpy.jpg create mode 100644 demo/img/sophie.jpeg delete mode 100644 demo/infinite.html delete mode 100644 demo/infinite2.html create mode 100644 dist/angular-carousel.css delete mode 100644 src/directives/rn-carousel-infinite.js create mode 100644 src/directives/sliceFilter.js delete mode 100644 src/services/CollectionManager.js delete mode 100644 test.html delete mode 100644 test/unit/collectionManager.js diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..44491d3 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "bower_components" +} diff --git a/.gitignore b/.gitignore index 4abd5fc..55c5256 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.DS_Store node_modules -components +bower_components +coverage diff --git a/Gruntfile.js b/Gruntfile.js index 2982c9f..9eb38c3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,7 +1,9 @@ -/* global require, module, process */ +/* global require, module, process, __dirname */ 'use strict'; +var path = require('path'); + module.exports = function(grunt) { // Project configuration. @@ -21,31 +23,39 @@ module.exports = function(grunt) { options: { port: 9999, hostname: '0.0.0.0', - base: '.', - keepalive: true + base: '.' } } }, dirs: { + src: 'src', dest: 'dist' }, + copy: { + + }, + autoprefixer: { + source: { + options: { + //browsers: ['last 2 version', '> 1%', 'android', 'chrome', 'firefox'] + }, + src: '<%= dirs.src %>/css/<%= pkg.name %>.css', + dest: '<%= dirs.dest %>/<%= pkg.name %>.css' + } + }, concat: { options: { banner: '<%= meta.banner %>' }, dist: { - src: ['src/*.js', 'src/**/*.js'], + src: ['<%= dirs.src %>/*.js', '<%= dirs.src %>/**/*.js'], dest: '<%= dirs.dest %>/<%= pkg.name %>.js' - }, - ngMobile: { - src: ['lib/angular-mobile.js'], - dest: '<%= dirs.dest %>/angular-mobile.js' } }, cssmin: { combine: { files: { - '<%= dirs.dest %>/<%= pkg.name %>.min.css': ['src/css/*.css'] + '<%= dirs.dest %>/<%= pkg.name %>.min.css': ['<%= dirs.dest %>/<%= pkg.name %>.css'] } } }, @@ -59,7 +69,7 @@ module.exports = function(grunt) { } }, jshint: { - files: ['Gruntfile.js', 'src/*.js', 'test/unit/*.js'], + files: ['Gruntfile.js', '<%= dirs.src %>/*.js', 'test/unit/*.js'], options: { curly: false, browser: true, @@ -81,69 +91,50 @@ module.exports = function(grunt) { } } }, - // watch: { - // files: '', - // tasks: 'default' - // }, karma: { - test: { - options: { - reporters: ['dots'], - singleRun: true - } + options: { + // needed to use absolute path for some reason + configFile: path.join(__dirname, 'test', 'karma.conf.js') }, - server: { - options: { - singleRun: false - } + unit: { + port: 7101, + background: true }, - options: { - configFile: 'test/karma.conf.js' + continuous: { + singleRun: true } }, watch: { - files: ['src/**'], - tasks: ['quickbuild'] + dev: { + files: ['<%= dirs.src %>/**'], + tasks: ['build'] + }, + test: { + files: ['test/unit/**'], + tasks: ['karma:unit:run'] + } + } }); - // Load the plugin that provides the "jshint" task. + grunt.loadNpmTasks('grunt-autoprefixer'); + grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-jshint'); - - // Load the plugin that provides the "concat" task. grunt.loadNpmTasks('grunt-contrib-concat'); - - // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-cssmin'); - grunt.loadNpmTasks('grunt-contrib-connect'); - - // Load the plugin that provides the "watch" task. grunt.loadNpmTasks('grunt-contrib-watch'); - - - // Default task. - grunt.registerTask('default', ['test']); + grunt.loadNpmTasks('grunt-karma'); // Test tasks. - grunt.registerTask('test', ['jshint', 'karma:test']); - grunt.registerTask('test-server', ['karma:server']); + grunt.registerTask('test', ['jshint', 'karma:unit']); // Build task. - grunt.registerTask('build', ['concat', 'uglify', 'cssmin', 'test']); - grunt.registerTask('quickbuild', ['jshint', 'concat', 'uglify', 'cssmin']); + grunt.registerTask('quickbuild', ['jshint', 'concat', 'uglify', 'autoprefixer', 'cssmin']); + grunt.registerTask('build', ['quickbuild', 'test']); - // run devserver - grunt.registerTask('webserver', ['connect:devserver']); - - // Provides the "karma" task. - grunt.registerMultiTask('karma', 'Starts up a karma server.', function() { - var done = this.async(); - require('karma').server.start(this.options(), function(code) { - done(code === 0); - }); - }); + // Default task. + grunt.registerTask('default', ['build', 'connect', 'watch']); }; diff --git a/README.md b/README.md index c14c17e..05c0e08 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Proudly brought to you by the [@revolunet](http://twitter.com/revolunet) team. ## Usage : - 1. Add `angular-carousel.css`, `angular-carousel.js` and `angular-mobile.js` (from this repo) to your code: + 1. If you use bower, just `bower install angular-carousel`. + 2. If not, add `angular-carousel.css`, `angular-carousel.js` to your code: ```html @@ -39,46 +40,26 @@ angular.module('MyApp', ['angular-carousel']);
  • slide #3
  • ``` - 5. Alternatively, for an infinite carousel, use the `rn-carousel-prev` and `rn-carousel-next` callbacks : -```html -
    -

    #{{ product.id }}

    - {{ product.description }} -
    -``` - -The `prev()` and `next()` function return promises containing the prev and next slide. ## Features : - Mobile friendly, tested on webkit+firefox - CSS 3D transformations with GPU accel + - DOM buffering + - index data-binding ### Regular carousel : - `rn-carousel-index` two way binding to control the carousel position. - `rn-carousel-indicator` to turn on the indicator, see demo page. - `rn-carousel-buffered` to buffer the carousel, good to minimize the DOM. - - ~~`rn-carousel-cycle` to have an forever-cycling carousel.~~ (BROKEN) - - `rn-carousel-watch` force deep watch of the ngRepeat collection (listen to add/remove items). - - -### Infinite carousel : - - You can setup a dynamic, infinite carousel that will load slides on demand using a promise. - - `rn-carousel-infinite` : use this to setup an infinite carousel without the initial ul/li structure. - - `rn-carousel-next="getNextSlide(item)"` : callback called when carousel reach the last slide, that should return a single slide. great for generating slides on-demand. - - `rn-carousel-prev="getPrevSlide(item)"` : callback called when carousel reach the first slide, that should return a single slide. great for generating slides on-demand. - - `rn-carousel-current` : data-binding to the current carousel item. will be sent as first argument to the prev/next callbacks. ## Todo : - - memory profiling - - optional auto-slide - - buffering : allow buffer size tuning (default=3 slides) - - buffering : add intelligent indicators + - see the [TODO file](./TODO) ## Inspirations - https://github.com/ajoslin/angular-mobile-nav - http://mobile.smashingmagazine.com/2012/06/21/play-with-hardware-accelerated-css/ - - Thanks @ganarajpr @bennadel and angular folks for all the tips :) + - http://ariya.ofilabs.com/2013/08/javascript-kinetic-scrolling-part-1.html + - Thanks to all angular folks for all the tips :) ## Licence As AngularJS itself, this module is released under the permissive [MIT license](http://revolunet.mit-license.org). Your contributions are always welcome. diff --git a/TODO b/TODO new file mode 100644 index 0000000..d7220a9 --- /dev/null +++ b/TODO @@ -0,0 +1,34 @@ + + +Carousel v2: + Base features: + ✔ basic ngRepeat @done (14-01-04 20:22) + ✔ ngRepeat with filter @done (14-01-04 20:54) + ✔ ngRepeat with filter and track by @done (14-01-04 20:59) + ✔ template based only @done (14-01-04 20:22) + Bindings: + ✔ should have a carousel-index binding @done (14-01-04 20:22) + Buffering: + ✔ should optionnaly buffer the carousel DOM @done (14-01-04 20:22) + Indicators: + ☐ should have optional indicators + ☐ indicators should be clickable + ☐ indicators should be customisable + Animations: + ☐ should have some builtin animations + ☐ should be able to customise animations + Bugs: + ☐ bug when rn-carousel-index change while animation from outside + ☐ handle touch cancel + Advanced: + ☐ optional cycle + ☐ infinite carousels with slide generators + ☐ optional auto-slide + Tests: + ✔ setup karma @done (14-01-05 00:15) + Tooling: + ✔ update grunt @done (14-01-04 22:09) + ✔ add autoprefixer @done (14-01-04 22:09) + ☐ template with code samples for the demo page + Docs: + ☐ README update diff --git a/bower.json b/bower.json index 353a545..b02d4e9 100644 --- a/bower.json +++ b/bower.json @@ -2,15 +2,23 @@ "author": "revolunet", "name": "angular-carousel", "description": "Mobile friendly AngularJS carousel", - "version": "0.0.8", + "version": "0.1.0", "homepage": "https://github.com/revolunet/angular-carousel", "repository": { "type": "git", "url": "git://github.com/revolunet/angular-carousel.git" }, - "main": "./dist/angular-carousel.js", + "main": [ + "./dist/angular-carousel.js", + "./dist/angular-carousel.css" + ], "dependencies": { - "angular": "PatternConsulting/bower-angular", - "jquery": "1.9.1" + "angular": "1.2.7", + "angular-touch": "1.2.7" + }, + "devDependencies": { + "angular": "1.2.7", + "angular-touch": "1.2.7", + "angular-mocks": "1.2.7" } } diff --git a/component.json b/component.json deleted file mode 100644 index 559e09c..0000000 --- a/component.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "author": "revolunet", - "name": "angular-carousel", - "description": "Mobile friendly AngularJS carousel", - "version": "0.0.8", - "homepage": "https://github.com/revolunet/angular-carousel", - "repository": { - "type": "git", - "url": "git://github.com/revolunet/angular-carousel.git" - }, - "main": "./dist/angular-carousel.js", - "dependencies": { - "angular": "1.0.6", - "angular-mocks": "1.0.6", - "angular-scenario": "1.0.6", - "jquery": "1.9.1" - } -} diff --git a/demo/dynamic.html b/demo/dynamic.html deleted file mode 100644 index 0363220..0000000 --- a/demo/dynamic.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - Fork me on GitHub - -
    - - -
      -
    • - Infinite angular-carousel demo

      -

      -
      -
      -
      -
      -
      -
    • -
    -
    - - - - - - - - - - - - diff --git a/demo/flickr-full/index.html b/demo/flickr-full/index.html index 2b3e107..e8028a9 100644 --- a/demo/flickr-full/index.html +++ b/demo/flickr-full/index.html @@ -105,8 +105,8 @@

    Created by :

    - - + + diff --git a/demo/img/grumpy.jpg b/demo/img/grumpy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f7fa1beafc1da1311da4ce8532189457d3f3dcae GIT binary patch literal 40046 zcmbTd1ymf(7O309;O@a~a0~8EaCZ#>27=q*5)w2C?!gJc9fE5hxVuYmch}^RbME`k zxp%F5-&=RjTHRk&?UKE#dS+L5&!4$Js{pp5tb!~60)YVe=MV5_9bI2RTKbK;rkbpR zvdnV<0HDh&+c-MGVFQ4JqZ>?9PKrw3z>o@Q1b_oj07QTj0L-AS&MI26+Q73Y$VgMU zJ}dp@|H$;|KvG+ z0|0@mXWzv9C(k?u0O~^kfN0@Ad9+^v04o>(>PG*|9>Txt#oEoyS?J|UPft&F8%rqr zUx)r9|DOu~X#VfvzxreU+uuLFqk3ie*38}Bjq0ycp-%Qr?l3A>XEUfJ72E&1i2tuE z{@1YnYaFbamTxU#mX6O|={~PA8%L|>>2|cRakFu9q_T1R-_7v=DG0S5pEcmjSv01yg<12I4%kP2i0xj+$64txjdffk?x=m7?SF<=^41Xh79-~c!U zu7QW=FES($1_%#C459?lfmlFXAOVmVNCu<~(gYcROhHy4N02+n4-^Cn2gQL>LD`@p zP!*^V)B)-Tjf3VvYoI;QIp`h^42KSf4@VA15BCyI08SE42~HdCHJlZk3!D#JFkBQ| zGTb+~Qn)&}4!A+MX}DFm1GpT^2xJH> z2to)72>J+C2%ZR`2uTR}2(<{^2-65#2-k>+h=hm?i2R81hz5wZh`xvsh#80#i0z2u zh#QDkNJvP;NGwRANNPxCNNz}>NGV9ANI#G!khYL+kIV! zVMJjRVRT}wVBBKjVX|W?U|L|l$4tYl!<@i8#zMiO!;-`@!ScaM!m7p^#X7`B!KTNS z#x}$D$4z=^;q#_7k|#YMuU$CbggzzxRD!R^G|zysq!@TBpe zctLo%c-?qg_=xxn_zL*8_~H0v_#^nI1h@n|1iA!X1Zf1V1gnH#LV7|4LVLn!!taDL zg!eDVUr4^NeDV23`HP7cH$j$DpKPFzk!&Opv4&T}qiE+|(T z*AzDfw=DO2?gs8N9u^);o=l!OUOZkE-jBRLd7t?B`CxqIe0%(~{HFZr{Idf10_p-0 z0)2uAf>MI-1zQB~g!qKqguV-%2(t;>2^S0RiZF;+isXuHh|-9fiDrwgicyJ~ihUJZ z6{i+A6aOZ@E&-9SkjR(Vkz|szl`NG!mg10tN!3c-NDE27lWuk>?<6Q z9ZVe>9dRA)9J`z-oV=XIomreiomX9iToPSQVM?%kSCH##*9JHI=U{5cozXqSea%D6 zBhBO1Q`fWF3&+dRYsj0~`?L3skE~CgFT5|*_opAVUx44*JIQz1{vdyI|DW$6?}OiO zeUST57=RjJ7cd;i5f~SE8Kf7~6igocA$TK1E~F$BGZYp&`%(B~)+hK+HlId5bAL|x z{5#AdY#^K?JSqG!0va(8$r+g(`6uda)JQa6bY=`?r%9z%q?4t8PQS^p$e75K$Slty z&kE1F|7!DfE?X|U?i>BLq#VQ?kDTpX-Q3X69y%XIJMe=62`p=g$^A79JKqEFmm~ zEn_byt&pvJ`^EIDVwG>Tb?w#K(7M+8;s$i%VAFN;aVvNmV>@Ywa;IpQYqw=jc5iIo zXn*U#`QYI&^a$rD{h0B%=0xIT=v4o7>kM}G=RD$q_@dyF=kn*3`qj#{!}Y^W*e&sG z;hn%;@4epr&V%P8(qr-y(^J!LrQb_`9RB?Ivj)`3c-g!K02LL0`8gUu1`t8G0Qi|e zf1?Qy$#Z=0@3=x2MEVb#fEfRW4%~Ag=kuNec#a+b;O$47e+3nP+0t2;pye=6BHa0`tj4}u(q`(NyO zb^-_v9v%#j^w%yBoabM|ao`cCIT3LsHIU3)@MyRKknyErv#UB#Al#a#1m>`DR6<&w zHM+CErv1yZ|9^%B{$E-4k756@YXLw9gPtc3j01=Rs~#NfOME|mjUbC)`q$oNjF#AG zlzxO#Nc~_&GHC$+;?-+dAj?f89x<{3?$0tAGg6rjRjOU|7+kSkM&JAS%ou+&q$%4v z)a`!NYvazEduiUXA-Gd!qso@jzf^1ywN0Bz3?D8O7$DIPj*nj{cGW#Lgk@Dvuv!wCABb^NATbW!XCHbiZmG$s5zo20lEdvw3DAs zFo1dLii9iQvhYS;_80}wwd5sZ&kKmMRBhC-N9b^ycdjnyr+KsWH*(1ylSB7W#4^0D z3zN8Z>vhVa%_r>-OV`7e*%H11_&7H%0Z(4#D8u!xg4*_T!jg0_Z;;CrbnZ;^SlQCW znTYHUP-=fHnJGzh)59eDnn=NzKMv4g1>NCe3VH6Sl;Bjh>x*p<@~dZbh$5*bDycUF zr=Z3;rwEW)Mw?iZOeHI}FvrOw+1$JK9Z0g%u|(#}io|h9kVgq^PPBcEWyK?NiKuM9 z?lz>@8r}#*ChCzF?Jckk*Vpnv^>=P?#PUzcNz>x_3^gx6XjtrnoM1`$>V9dg?MYP6 z#S|1+?ic$5l*#es4s;9RJN6<`ZIHc_(bB^mr{Fvbv-k4s4+3h^qDbQaipGQ2$@;bq z3dVODpu5MuPfN}%JAg~3-E?i#6*;m6y%+&s(U!Mh``)OcCt9wOr6YTVdBA!XtbTbP z`Q&Z_R+S|mpn1@QXC?(@mXf#N8W+jp6Y~ruC(+Mj$32Fe04UP_7b50@dYP>Qc@-izQxl zI|!O6;;ARK2zCC{{Ne4c4$LL9^WwxnRdwSP>@`)#;xC)UK{6OjtX89W2}|fUqj1n_ z&FD#rF{3*fPYe+mICou)R=hkv5UNsZ95&f!%M!nRxj~!6-NNs0Ii2wRi*?6Pp~6zP zXq1m$b<|*v*2?GMk6lIzlxllTZCPcKJ9{@wF6hOyAshBr9aK?0ZLo3*b)THpVFhb9 zj*eD654Gf$sM|~O#!^E{YVpJukihm3;YKRTH-=xb75V4^`pt(1O|WUKs;;~^A(vTr9SQ)it*`Ufb{ z%n=mycNulG5tzrH9&nN0-{wL#?OL@0D4bEsXd?2%7YCW%(u=`Vy~VTe=Q$}XUOzZ1 z_y@dFu1CJK;GLr;7lUES(MGrn6oro&x6>`bl8GU%(aILOVI;;j#%8hdJx9I8 zL9+#5$`F-6E_oltk2Wz0{T=r2U$hBivs4YL$3rPd0|EhZ;6x^ckg?>u+PMSrZTn(Y z+H4qE+1CmA38MtI3jwn}1`$NEi$lhxq%PmuNF^)BYhw7F(_yvheV$OdZCQZIwPs^> zai;jEOM~~s5%q{cBSQsbmiMI#47(BLi74z_c`{0+J3BUZ*SjHBg&%LYd!~>SeC%c% zhqCuu#bb5-#KS>N)=NI-v+BAk=+_)NAf#6~K2NURbC-NhUiXoI0~a|V_%Jk5gHH2Gz4bO|RqIqE$EFvZlI>MNWR z-=Zfg8di@kp64#JOy*8AewB52vHqfEvi2obGodw+iev8iC$G7jeUysKVa7amJ4YWP z!3){mDfvb^#bcKXO36$wa+VGs?lBGKJK=x`=5tB2QGb_1|HOLUag})j|4}kc*~8)} z(qlmEOr5q-kxz>6Jjr`Cqkv_(PQNf#iP%5@UfEh zcedp(p%x&YJfxXzQ?*Hw(tHb+;Nw>I>BHpH zo+=W4Cu%b{3@fM$SqgGsB0P_gz5O)g$a!dY?3|crYpYbW zHXRgvI1=CK4>>~$wg}tr@km0X6=8TXvYPVX6^P)mWm9d^@z%Kd70^bzXTn$`^B}db z&lzw%C@6NGPT4$4mAT&b1}`vC@J;rvR$*?mrhzo0NFl_Tp+QvCCzB;my}GeDj>5Ch z;-NRtXzy2^@}#v2A}O(m)$z`c0`eauk@gJEclBge*5aD799|_MW3+t{Y4LBz(D(&@ z%MpCTHGLh16W3Kvba@{q1hY|8s9M>!|4REw_0Y{P?!DS+v2JBv6^#B)eng1C-1S$$ zuyRU*C+!6Xt+55-Lk`)d#XD{lmb8Tpa5c89)KR;**F}Gxxgm>Xl!f^cpF#DgiP}V& zLM|N(=e7(N_h(N&1p%VHJ@vVIOV4IhhDMYJIw68JEWfBPQ;*lsl~V2JR4cQF60H0nx)_%ji$g~d+bFE5`Bis{xtg_t)c z27CS2gZ-SS^@G@EjnSG&E>}0@OQJ|@CcTN#-Hg5^uETVV4YTEu-9HZlX=GYN5@l#N zE;dpx(=>GDBH{Ois|#u;r*$ScP$b*QEIi46yY~tjABOP6LL_32xX8W-j7Tt0en85! z)ndvG!|kQk1$my(BA>;$P6eqI=8+!4niAUx+O%RjR{aYWnjkD>wbX7tPKSR0k5jKB zGnxM8+EflX0E&_Ro2Z;@;YFVR5J##)1?2dsIeB#xnuIht8+OM}T0LVY(av1x(qIwe z`;N04a}PHu#6XAWm9clk4y%wS8P=X*M>8HVdx33Lk>Bb^XEFQhE8c#Z2`8AgGInkh z2;p;Y8H%-{VYEhirMW?qRpELFP4b6;S^-vHDEJRBtMkG+oQyjL?hwEh*w{XNe?OI8 zYKOP27X2IKV5J(})nv}SFQl2+^osI;YQO7-PEF1B`aIn*xRG@Hw^deTZeH;+C9gF< znm5>R7~45$OP3+Wi(JSx{*89xD4&op-fNrGsA!M+87@*C$>aiAh@%g?_Gdsh=emX`rii*F2! zQK*|#23CXm)&fSI<#^Yob5{@DdThR=Dpv{`-w3yzQkh)h!YyvT8D z`SRv$s&X-Vck+8m9}ntX`L#+}wc(NR5iG4EnVwLbUXjezP0;O4zV)|g;@hgy zR#c65S}HuPd2XY7eVP|K=tP%h(u!B}R@jn`I>IVsgDk5+@ye222f9P{T7hr4kcu;L zt^@T0=Mqe?+qHk`us|tcrJCc*`{n8g@-DvdQNP%w`zIE@VSC$sAwQE>j)jL2DL~;0 z=pc6BH`Ps%G978k%nVC)vh*=Xd&AlI9Hj_Wl}imxpS?UojVvxnPfvebzCoW!*e9ON zxAVh|MCua8sY<~W9F#@rAoX?jo$(HTnrR)e=c<)H(I0`>D0w?9twQtshB8u?uI6kN zi_P!q+gA9=l9rGZqf8a9SZcc@qQoo&gavxAq`Y^|io+RVGgi9M`9j(|-u4d1AKdCe zJb4>-7ElIZVkg96JK%V&A=+8VA>#C>2^8Smd(?P6^AkOfmB&#>!!DL)K{<1iwK9(< zy#eP`M4L1IhBd>Twm}-7R$B-=HD}cYuJSR_L%XwUuaC3p4gIVb#clSga2Bdp_=B`6 z(!)!wm?o-KX>QzZRSpiHum{#^;v=dYw(%|V!gJx?w-OF)5e}Gm?gcL!5Ld@(+ zWcK^FDA`f&X`cMg>2bs$Dj`s!_z~H5RR-6jkQ4Hw^2{TFCmGk<3ng#xl0lWgjfMEn zF5lVM&+W`jS3)*3TVhqGJ6(SOOs_x=NP~6^_BxZ8G4)aZ4pPKy>>C6|NE3l}v>duUh75dSV)1p{D4XPz8h}Ip5VUy}uT>9sPtcZIhFf?O1 z;U!A*R54LBjUc-S{Dqse!45j+L}%$|SsDSF9|@)8?W=@8vVM*36nV0iAD7({)EhAW zZE)w^cM$E;tLS*Bsmmr85!eEGw~?9Gv|aK=DI7MD-FcUy3ucIMnTzpH#E5@q54H0d zZu5oe2qEsH$o!>vwL7^bXOAnt zP2UhjgfYmWzlP*@yEr1qP;bK06#0T5$|~b1zjR@A(0G-$9rAkpJFO|Ecdyn->NSKw zl?k$A#jmMnC5`Z*o-+p=0qcy7)>x=497(m&-)-wwz_HPs+AK+zK7B)W?QR}nl1Q6EG4#p9lY4f&G2JgYu}IG;CBUk}P} z_kppb&eJ}BbIhgFmdBN^nRc8qwxVgMKlsL$MZFIC^1m%I+pfdpsrjjbnWM1&8U6dtriD$LElNOq8ResmTa?J{PfPq(&k$qJdYhk@K4v{*~_n$k<|XE;?;xEiDzW3s?5QZ)5AN5*j< z#nNB#VSDbV;B(#1#Bb8Gx}fsK1vI0EO&jdvh;)wjQAm{6iHVLfZPBqu&$rlLug>tL zoBjO{$lMME4ou$36fROIsAs&eHt#)KCDHg!!l(>yA4#<-HnEH);wEaF!EufHUjYfNK~S@tu^K>)fo_@ebV~}Fe%VHN5OtA`w|5Q{_N=kfPug4@bg_cHcZZ=2seZ+c$YCZWi`M89wL^{A5B63qkl-Au zT6itPQ>fqKH~@}&T*Z{edm z#1MF{vl#C9SxHFWSHE9E@;_RM^x$0s#*=*_e)BpSz91<7sKH@m=e)-?yp2oizPjpG zu6sNxo9-rXKX6qZCY+)>ci0AMN4WWvXUSY#8EWdYSzj>Ic){S6 zGn_-|ouw5-V*2V3Q7V+UgJJUGzyvRHWCFnoy*nJq_!6A$*cJV=hEj5~CYW}!q!Gyj zOBHM7TA;`WC1-3F8AOZGnFNNA%U@DVcfYOY-u@0JWvS3<;YhU^8-1Wh6vp4$^MXR( z{A;lV;ZBsx2xH>JSgXWR_T9TSdtaYFz*UJr-8`#JLw)_K&Va`E)BR&rH<#H9+pg1;yj~R@Hy$f5ap~IZ-78kOO&tvI z)8mA}C$qd)^D2%$#;wt$#A=C4q1!8qD(>|%5hL16KSSe16-JO%eM~JL^s0yrlBKm_ z{0d&j@Rc7w*VCRc!sARia{!{Qsncy{j5Q++-C`K2BO_>AwH6BTF!0DyX0RtghWwWy z?@-HHE;*jJM&8I5)C@=kI+r46#^qowHfdk?ykRF-D_5Ex*!4vbvnprI+-_$>X`YOd zo5K-_=tajHqLXYTUs0_mIw;aj?%G9W`Udaj`uEFgVH>@+okMH`b&43iH%LMn6eUcAwLukB1u`|ndsfb5O2+jZ@;tbm9Altw`O#Hq<`J=3l@JgDaMxcO97fSK8LH5H$Q4EOe>-ov|@ z=xZyZG~*L=lzwE|C%x1i{kLwivLRUkSAxe|m0reJRV`~_>4=i)t}C@s>LUVOn9p-EFvwbU`izc={Ey7uep8-6FtbdB6hANwH7L{%FcgPFC$Ks3=t5O_0{G4 zY3rckO0>dv>r{AazU+>?rF4r7tHeuXy9`WE5< zav>H$SOPIr5c5c7X*HqfUu0r3q#?CX2!3j^7n1U*KrQ-~LuB!rk?oAztHs z)qG4+aThKUJYxsaTs?2H0b^$~o3@d-4S} zW|Pqoe@o}UjcAX{hj;p*EzC%SR1J;VnIyK3N{C(ZGSTp_w)UxQsjJs5)i>5>o7f$1M~cF02s4ZBXihyd3pkW%030ZEHF~$+;t(E3|2m)tU`tQvt$35C z6yGpCFpt4i$-F}0RG5JUTtG?xNoG{-w{4dUaMQrUZ zlWj66`mH#u9&>0vnw@36_o51FO#&UeyXx-zcP01VjS7tNqRbih#hR%DR7a5Qh$|!k zvT-|G#n-RAw2#a}fEe$cu;wLR`#|}aas^EgG5A+Hg%7GiUB}#7i)+E_(Y#*vRH5)5oc`!C(T*q&LtzRP)p$n5IVfpsma3$iPnMMx|63YtptC1V9(2Z}&dvRr9wicf;3-(w}Y?dK2OgH{nOUwwV4+ zAX(Xh6=|s4YjmyKK}Hs*D$#&%xB|}$s(MBjl=HLg^#E<#TMmMNp0zATmdvu0T#ApV z{^ZtW>rBUNM`NR|?%ORN+>`^N^99OzRTMHX^S-%xzQ?>|F)EX~G|X9&q?qa>nx|4< z-Izk%zqX}E&55PR%dxq3G1`l14`#Kam5zwX?T->Cp`-5R9u-kBv#rBv4QVmA`6Qnx z3o_sQ@E(o@g~x5efqPpV`?j~Uu4+HkBgg4Q0w1KG2|>bgOF`^vkhf^AxO%IC)aDnu zQ_U~z{aD*;AFV-aO%w}vnNiFf@goGPomOQiM9uMw)&=)^LHLn-q{kmX_4Kg$(tN|B zfjYgAc&A}R;%Z-@+t*7Gg{6A1d)@d_WM*Y?=fXG>lTx($vb=~p3VUY9?AyGgNUV41 zgdBrF1V-0Rz!LhbsDl1p0crKF8rIz2xe;$&hLaOTHtJodQ6g4lY(Tw$@x_P?tS7%f zIXk=Bdlic~w{mHJA+fbZ*{_fFYa+q2n%7Yb*`~9wPpsiZUI`6OmC*xJ>Esci?)L#O z^8h`Cc^wzbe5nId6jRvLt@O3_$fuHTPpy}pm5a6k451fFZejbBO&=JB;oIMBnbqV# zslNmY>xrb~(wsm?+c-;M2ZV;<%*^{FZn$0e8+2Ta2YbC^x;4|o4$z*O)uCB_nQ(8V zVEBzp1P8{rp=H%IN4^|;T)CTiaA@B_=5!h3+*aXei9fbY?3@=(UulDbOm0*B)?(z& z=1v7T?DT@cCwgr6TkGWHyk#_$8Mm^iPvpzS-EV>&8G74TGkU3rUS|2bDO?3qF7K=S z4Ksez2soX@dW<;}Vg3PDMA(rw?)56Z z3^PIEaY*yM*;DeB3iod`R{C<(CVwG(*+yZt%As2F2)*kQz1@4`sd{95N@v}Q+4l27 zr`g*fbw+N2pc>!Sb(_zbpAkO&-U@9@M}bd{(|_lu`T5Hl8z1MYW+{|VXSm2a26XR7 zCSN{1ZmXA`YbA+#QQPtsvB{yKGK-^+7f2BsRlK%LVeCT}%kSHL9Ii8jUIkcuif>H- zr^B*8tOg49^|qR6l8`W$@1WQ{h}@=W1X*U@A+%r=-@?|kg8AZPosNrxj#vaHgTLD$P2k-(%63EF%nXs!*O4 zrTnx|e4{e#f4R8d6v35<=IV&fcF45OtglV&=Hl^%bKi4(KrV&u`;mzc0wo90CH(Ua zjA6)KF*QtNMXhE~^eF{0GMUFZmdQ0%4JEz;ux%0%-25cZ7&_zZ#3;^~qPT8S(;Zx{ zKXv>>0C7lcOzkujI`BEXjgGGU@!=1!fY%HE4MY0<_ zA*&T+eY>N5Yfvs$;wexQx3b{-QONJLQNN}?G~j7G{@Ct&CX-<=cW3L!n+Ha!l$_6x zg>MFzB+Q31T}By15v+^p#jPwn+DONDCTXIzXW?uJUnbQl+@(s$qR7iCy;H^axh~2` zmaG|-syaJrOAUWYGp*!%eAgKNL>1NiB?41a@TT0mn=X4Eeyef8=C@#Fv#CXlH0%48 zr8}#)t4N?A*QM1b$#MhZd9A7?o0}$+dbe-NhD$ZJv~d{UKVxrsVgtefI}ivlaVhKA zojvT!J%>{BoI@f#_rf6AcR2_OO+&qKU@|E>*fo#~iELV?ZZJs9^=!LQtlFud3+}V2 zXW*-y8`BU=Q7pgTwaYTrDh6ck4Gn=W*(5CACniTH>@@b+W!DVhXAJOb3@C2caaTt2 zVd~>W2~S2OXz}ce{&owMuS_GZuT@!d?LkyiZS}55=~i1%sm>QW)R>G@b#9i} zGI-xQ7l+~6JrD2H(9c)Q+-%>mU_{Bev$S)TlX(cEi5#;1z;y_JqO&(;3W)kly4WZ9 z1QYj+H5(zp$M}2@D0iY~Z+elK;@6GU!Xao58l9ab;QF+re|UmKw7{Vtt}#i#S9$Ud z-YlqwOt#Uq;D`9ey-w{{#yKb=K33BT$a!z2Fmt zzsyz*q~@0^*-(_Mi6gxXZZXO+>r^Qk_V?1m? zae-8}xax#Z48Z}{?w!;msOGgoL2Y;p32B3}rmWA?tmr!qJL1WGZCm53Q4AYr8@(@~ zL_m#2lKyHBF?z84Ku#mVchQD&f6WS4-Qz10rr_YXQ1gkGE8yatU(tKUwI=y7pEpzg z0G~DOs_a^hR*G9MK5+i3b)NE!T~;NG9QD1m!fnfZ( zQ8G2tvr+}ib98#!9y#epeTOux6@yjSZE1p-V9;&2(Rr^HbVA-PkeI^V&rXD`aLwE6 zsOOp|=751ku-xln;WYL8UZ7KU39ojFWUEVccP|@_yGP{ZdOuBbqW&TCW}KWV8a<5NUIsioPx9H*d$PcexhWzt~sa11x1jJK75(KQE*vvnTyz;3P;y4kJHm zP$)e5tUlT+>jL2IEwr=2odcBZ^#j*O2b zcw3*%75ao*8b;Bd_v8%}kExf`pT2Wy-$f_5J7L-Rge-T>M)Ktq!ES!O%wRjap<(Nz zwTcl}TsFreE1cVkex&7lg)Bv@+iCuD_=gAg=!hC^{3L?ww;(K6!)4 zyu-v!$xFVAh7@Rq3~w6D+i@Zhc|w9>`>1?VJ*X8(DKI8YXIu1g4NKX0JaUbVV{arr z#`cph5=45Rx9c^F^;<=1J1s=%SxbO=#1b#6Taq^yi9Fed_X5WC>vay&Cp2~q$KHsE z$8WPnw91lxT|Syg4e4%tZAl#Y=0+M88z+dAEg*WPlCLy&C2T2`t&jULrZfHdcZ0WU z-X@ibxd+g!ib@`JiQZ94Nk}f_j#DKie!D^D@1MYjq8}6RVF=lrADu$zVuV{aGsJL1 zici0sZ$r$0+_nA5mJZI?o{13|KBE)7ciD}j<{~P0q%*K-1#uRc`Mk@+R#PblE8{>9 zXcrZL<_uE6F(dz6=s?cXG5ex+FIhQtqw|}RD3WNbz6@U^UuTb zuJb!iogBuai@#GOg`5UtYP-*+HU?5**FD4t;)E#d9gy){xN$gWo{ z&G4j1&m6wRlAcsOw_;rg5*wTNjc&NC-(9v_DOor_Nc37wwIN!}-g_uU`D0KAEg2jZ zq=;aqFkOem_8oDy7ve9KnwnIkcS_2frMf4a7xdU1LkhGXlQ`dvb?uO=@#;gmg;W%*_$xLGH8zeJT~Eq zt`5^EsIhm=#ND>QUC1!;#82W6FrReF{bC4L>Q0nckJ-o9yrt=iqSu0HQLCfoJr1o; z>FMzx+r%;a)9P@9zaZ~0imjW#uFq4#_)>1O#gZ21!>W~y$P-I8pCz>+Ps7Ek2mF#O zQAK&XILUyT=6ZzEqRbSvk$TA{Su8d`Uea%0$;NpXVv4e%uVh_b}TZ?&Z0` zvxLGQma2dHM9FLg$(*86_ER?teec!EmmZ}6p1PkF4z3jq9J5Hc3)?9=`c>w=FWON; zQn}`rXO8z5HTixU*ljiqh zXsr-G(TMBSHx+w2mYAB7*!VA-MIsa^!%CRJY>Z~XnjUeAJ3wY*iDWh+LFgWYJvTk- z1vv9@RtAGOTu(0ac0CIqDYX$6xY$ zM?X`I*$UovuFJ(@gFU=YqvPJaLNTK;qQI?2TJi%?fA(?Cy|`x z^2lwvhbYTpHhk>*Iy3j78mhIcwYmaXhYR!3TX5jlv)*?FTMQFTaq{c1#<_)XUwLwm zig|WSZ8*%y_)M|d^i3S)?ONaD!Ecfm%-jTj0E>F*%Ohg~;$>BabhR>xajEgq&$_FG zQmzA+}&rsn?bZ3Y&MircXdou;V~NVsue$TFGm1sd1jmh6`f0 z1!;P3-$1^{E~{+Yhlw6? z9m?}F3JnG(g5@jLV%T8>j*x|ey#Okjmb>cw)Mk#y*Xvi+Eve)5cQ3V79M`I9HaSKo z^So>6JbZZ8qgXn>cfRv|$|EK+YM5A4IQS^}7{w&TN0#)lNV0-0WBSroXFW-mGh!2= z$7AQfs6Xaw$`8A;+}WhF9{4x{O(ENr+>(2%(`u1DPS!-@gvCrU<9px38xDCO1q6$U04 zW62h+rKD+pTVqyK(s9X0r+Ya?kzdU4>`UkH3(d^+b-OnL68f|t!q-EB7m9y?@1lmy z)D{u7a(({nr%#dHQ{$cR%rT)r0_IU4Na<_4x$N^>e`|bU3JR1$w{Z)T%B@LrhAL!9 zTftFfeM??_j^4j@e#sj5_1N~X`ea9&(;e`2ZxP{YLt}#`Ps^jt>mlifJP#pJAph{| zG_UKsq_d|9IRpjq6{K>Oq+**4jcMcdX@{I>J(|g3Uz;V-z&=A?D;Z zz}a~9BiOB?ayRLE4?ojh8K+NR5H$FX+eD1UCy^iejS1h6=-T@$3q>AQA*~zlFuC$f zZfrK;Q3{Fq8&S^LOav{s+57H=fkn9?qE#}tjvgT`7PAm4O0Pe8wja47>bTRd*c@Pl*4?yT0!KYLrQuc4zuzt0}Ezhbb) z>y96@c+&bqbA+i!Ago8ewY(|4l95jhWpDiF76>Qr*}qYD=a zZ0c1J?L!%kvzjP@%aUc5&g-NX?aA4n&=8l9H%PPn)rPX#J3~!cOBQn2u#m7@H}*&) zO%?`b1m4*7JVyDO4&Hp|H4!Ycgb@AQ!7929G}23&&Rh5@p76wP#hQFAApWV`W@Ja% zCfEC@H!@hOpLGJa5vBeq-EZLC*>B$9lu6{J^CK;tb9Zlpa$QDBi|dI$0D6`9P{CF2 z6v=jaS295f1jCwoJb{8GS=b6iQg6LKap0e? zziCZc<$OfxFWPF<{La;)Q=wqT8&$xBUBbmG8HMUVtsZ+U=TxCM%|doxJzrCSZ@kYr z=ubxptKTJvcBc@~7b@Z`% z=Qo^PPq#3|@e6HO8{b)N%^ORvW2wdErH;yK7oykz_1nV;pV?^50?u7oK0znK{p#0} zIm<~*u4aN^t3@LcbO!Idb^ET`%T?IjzKsTn7}y}@!J|17qV2uP<{tZYm%fuJHSSWM zz1X?#)-+)?O+!_}f!wvjIvffaI~vAKPAIiAx=q)gOEJ{C9!y*)PU#CiYZiswEr^rY z*UYchizmD}Um+fpoWX$@KN9Q3eJ5Zn8Pl65swR(-5 z7wo<@&FWO@7Ht{p2?%8TW4yCx!)%lbm;4}jWHxTxa5^TuLwZq2mchFndH zUMNYlmBpPUMIfE+SKybbsWo&g1;$^wG@YNEo*DTc!(*vDbVhH@D%!Laewv{ zdlW~2&o^Qu1%JCO^;o}Z2sFTsN|Oq78FgJE8K)o19atpW%!G^B`q00f&B7s{2z})@ z(ESOXIV$}e)X`Dwi_#S*oJW^Hvk{Rb%Gp7ytGEX36XU!UdjG=9yRF}at}Uk^o-Jd_ zQ6u4NKe36k-Ta_kgUah&mvtLgnMK#`HheE}{WGLbtf58VMY{!yBEk~r%jGGDO>>%t zK-pErTnno$b5xuQi+8!WR-c(8t^Jp8pZ|S`?I^K9gSPDjD}O)6&y1B7ZLx---D zweeEnW}=uCjO~4|i+lz87Ya>lo(G%8J%V~*rD%ssOisX8EXG2#K=;+|p&qf-}C$7UP%95J9C_5h3xTd?p zAO5;w?5lxJCd&5YOQ|}^Fuezv(y(`8o@#{@wPA_F>8#PVVfUj7_06s6&CEu<4*2X| zc!EF@xwFJ(*b44Tq@-oeX2WlSMLs| zgkB(Co4&K_?zM6A^%B@kIjjFvTUaYVAbCJK84)ra)%7l+>?pkd|IuUdc0Ljm>C~hlSQ1Ydh&&n zfGg%~>r4}_K=4XTldh`tR$>}nY;%qL1JK-v0z7$$madI~zxOXRUSO^h9rMW%Do`@7 z9%@`3gf(b5kQ5g|W*o%7UvBG6RiurWr&NYpYv@=3o;~ zW=C=S0lLKu&asHVVEUX_ucP)S4csD-qA10M)sAQLMW1Yq=(_4|J~MaYL=h_gKLD6O zXTNV{+s^JsRU@S}G)saoFGaMw-^pumgCL^}X_|D8wcIH?rDVqnI%laT73<*IRygZG`BGUn z6}O0&F)?;^7#TSHdRMU>PcCm#(g>|oNi2ghoNzb<{d&{0WvZN~sC+N58n=j`xRjQ6 zU?Ty7?12tsKky;|{OixgJ1ZMf_q9IaiYT@WD8?`{Nc0>5UppnMXGOx|+(?@OkPbGI zdLGA`l%4e&W*euFM>)^SDQiKGoRPJd7Qc(sa)5IUQMGpIOFE-Ppv~_HD*fqB?xbs zxg(5%4l|!@(G*f>ljYglJ&5CgFit3U16JBIC5E9OUSRTFml(p9BRTiYc2Kt|mh8=E zcL7nhjNo;Wi@kQft#s}p(EyEd-N3w?{Zru+0noX2^?c1o;jj1)CmFz#^UN) zKtOiKCmj!`v9C`DOPQQ?r(?JHf8nc33&hlK?V?d5Gh4C76(r=T2a(PX>M>tkMe@a5 z@@K2i^qqUhGihvL`#auQ$~MZm+!%V3kaO=^I=T}W97KL4^IB9=$s2-961M=J*#fcV zY^xcXmZL4jyQHv55*6Gq*(0dPKK_+l!?EX<+V$3qH3pa)`xe2ww0yGwya`8r$~&(= zg=Z-Xmgmp@I{1+uv3latb&4 zU=Pl%qYg`+A*&0GYhALnzm-NG1YDKQjHsJblyG zHRh^r$EOO1soQvjSS_8zu!#%Zv~#dstcBMgj9`4+5&#if~ZL_giA4h37#UN&ktc?~<8Mr0683&*Oh9vbm{X0}y0YfBi z^6hzJRwo$b<@$B&Qr*h7r&(`(3c$_3%#uv*ZU@brfS~ooLqd`%USA(6(+a!C%g;Yt z^roa|%X7`VM3GAqt<1h^u*ryIV2qr7IIYvroMskc)2cZ4z4DTafWj8U7_<$nyNVnxJ8|h0Oe)CA=o_|W(CO|Cw1z~=W z$z`f*kp@0()Gr7Dl&)B*C*{uvjQ%z3P~mvRd(zX;<(Cm@?!@V)0Y*vB%yM(k*W}5c zYF@V^7;l?_u#6H1Ym-zbJGN4uX9d16>SA4%Ljfi7oq+Wp44)=JqOUg zqfU~w{fWUkm7K6bdl^)DvE$d2$Kzd8sk;l2vj$yCB-%z)D-Dat+t;l(LAGrQ5;NOW znb$Rp6#&|xsD3g?H2ozC0D_tEK^bKBd(@mxT=5+yzH&TG(XLxnTIF8ozH zN`Bg}ZX|uaTeEV&bps=>wPPtYqdF40I$bwcyO{yCf*HZdK4W2k#&V?boc1-fC?;b$ zHKBfeZs^43Nqn-SD-#d_Q}@1M!S?s9+!7%>oEM07J6m|(?%Pn3Xl@tEnMdyeK1lhA z>5zZWulKHkI zND+eWI0?IP0P-+7_vF^LNX2SD7DQs zM^W$>!Pj39{A2yGbs9x!rHN(`s2g0zw4uq#+lD-!spNrO6sg?jsZz-LW8&tcZ7k7v zV#ab3!v6s6MFGYd5V9r+$3xTVJJC`}GZ;eWscY63zY{(O#i!Zhn=k(2FjjB8y&02 zoE&sLxKEjAQ`TXD%CKDIagq;u=Ww~aE_epH;+MFF z(F;7KVv&O}`HSu=wB zO33G-Q&ZnB?@770v3vDl8QjXMaIDzi5!XLT^Jhxus~KGM{R2=MR0H=$TZCZi<_->e z5<%nExn&C*b2fUlhm00PNXk6yrA(UMU1E|U4gF?njq@|R`@r+gEN$?95nH)hnMWh(OrmP|9MlaHzT{{WFy z6dbx3vpBvC<}h-J&gaHov=4!<^;-rY2r%cN{Cvs%Gaf5{??-GBleP$ZGB(!JFVzASTIM|2pGVD;HC7aNJ zn(l8y%jIfE>gR`iBR7WpE23WO7Z#d*z2p&yrMbCOVp#*^D-zpCIT^1Wu1AQiE5;{O zb4oDMPh)dkT{}RtwbZqJTHZZ6Y!%ck!`wu<0|2yOfx9Ca>snLcoK5wz6tl_}(&in< zh`bdgy`1`Fx{dwnI7sD?2;%vHJV1VS>5hGC>~ii8!^J68e9!RoK6e|$b!6J6xmV(P zyDUqkZ@81}w$|?)%`(hhK@9mLDmnmr4&5v2D?${YqZE=yfeFf_uP1hMT85#ei+EC7 z^Lq-;CxxS85mrx?n;%op)1GU~d))1{m56*VdS%qEbf<#OIM!&@E>%M@aKX1TZTW+6 zR1W_DTHX@5l#_|6KKw`tI9_p%{dmtx{(Vm8>&cQ^upxQDZbOc_^!BQ1z{|pBQ@3^* zasu)FGfpsaV$?`%FK_NQd8Rnm3Zc2r<6f;CGO^K4lY5;5!1ho>eG^8r+RnSj@dgAC zaoikYy18Q%b}9>@$asMfZl>}g&Aspw+hB|svLMzt7;kvWJ$JWuFjjHJX0NFZY z+*?Jtp%@AQ$@dtqSyQq;Vsqwa#vc;CDo>@n)^ge08KnfqPTXXk56n98>sWJHjYFyA z-VxO#@wT-fDBB^8rj=v^Jbw@)xb~{#Q`CI+b~bFT&b8v}eJowQrkJ-0X*`jh1LqmQ z>JB^B^dg*;dJ$dn!O3oSzaI2$8{vn7-&9``+)b&^`>i^`a^guO83ETLf+d?01^qg*ET8 zS?kMVCC#k%{{U>UJ4;1#5)vEAcHp{?#CPJH=uR7=p;{F_7jrj9EvM<}scGr`p5swl zjXnX&6`L^KK`zwI2|)U-2>46kA6gGQM2FS(D#^pTp9-T|P>8Jo!}Tnay8#D)#>X zUYhZl-JRHzjHvSps&4-PzD0Q}-jUeaiax^ld*NpAUxZ8CTM1q}2-e~<2~uJ%5CPO~ zVh%bHUfd|91I(Rf=6)x9Yt&=#uf^SJP-WBfjY{tEH5gQ3Jgdosk&?V}gs}v3$F6I@ z#86I5_wd-3k~}xWz9w{wP_wt0y!W^(6wiWK0HAr9Ir)P19dHkNpx9S4VI7Dfx0CUkh&l24mx2d?159e+$zRgKW8J09ty zc)(ADxkNXO8ISvNbNkrC94Zw9=NRwQd-SdsNcCw|UC%<%HHcul8g8j^3AhZb5=JZ@ z7bjz>9BppIaBGgO1FjVlJt|F3MJVx0_I6fPX&NGc9Py5$kAAhwDlE4oK>DrBO)Tqj z*AfBy(hpVj7#t6!V(GSOo`g1@GxAsULcQ`H`xw`;!+>l=O5!RRs2j@hYf6iS-Dj~1(KBn}o(>-;$B zk3cCPXTg6MJ{D>#aV^wg+6Ngid06ChXsE+t7HH;Tiw&#g4S5L|et;hvKn+_Ou6WBZvTL@cCRk`pD5C#Ft%bQSfu zD#}qu%Hrs_NuHJAdnt#8H9Ngt<{R5<7*=M}l0D0k2obV$&&oOLn)V}4OP(~O?_~D>j~a{{VJkF@;c1845BtC^!bY@bxXBg<4M6KAV5DX>n+=Yd4ZxuBc?U zcpPA{lx$ykt?m2!5m$4+Z1Soq%7XH&sB zEo^<+au<~ZDlpo6bI@Sd;!#KG7b{yy5Li^4w(Yni1IGXXR|-x{oo;$2m*M!PLveC5 zftbM@XVej1z8eUV)aZgVuM9Tvf~plG45-R+jCCY;uEvy4LK_^exh!_}-g3+*itHA^ z#_&J@h92F&O6I9{bU_@H7fF4mO{XfE=F|M!ojn%{WQo3Oh(J9`W6e?2jrgoo9JCar z%6d=3uZPm=cL!V5JjiWTN0x*ioO=E>>R|A0_h$|x8kUFFnkJl52w7po7z+eo5yJ72 z-=6jK6scJr7A9^==LPYLQIks0B`a$wG9d`a21W-`tZJ&eBgVJ9ephSz{6(zXJi=99 zFzybdVCSyhpOtynS34YU6R!Asr^lh*-rPdX8pRL}UyKGA032hUmD3qr9Ih_rN5XFw zX*w6gZ|%Pl=}~xxNbuK*ZSQrz56%HwyBBS;##i{xGE{I21q^nRSi)A7&Z>&=w~^2O z)*leOJ>z+7-@{2gj+bexUap^|T}UOCJw5j|nRWvOm2j=^#!lRya<(y5r5N>Fo(>xe z?5j!idwu7|7Vgh9Q7F%x!9YDQ+;jA=Ix*&Fr6!U;q3_vez#2ZS@CQ=SymMs+t7Qe1 z#mYl)FkvDCx=7!aQ^s;J_}9})ov0|uUqj<7VkI0;G#^v)PvSP66n7SSwwEr;O+wvf zNOB4D6qL)A?s)0gSIqKRpJUCTPeAbmcTvrzT^A!$Rf<;56`y*dg(r`j{{XHlYH>N| zBllO}4xGBT!Tk=^q7%NH^7*VrOQ1r~$bG`UO7v$N!1JA3OzV6v@X$v*^IoP^e4pL7 z-ff^9dhuR#D5%Kll~*O9wecTUw$t>d32?q#P_tgbqztSGP7gdB@mp4|qO>xlNw;(P z%=r7_``u^aXNi{nFEdTMS!`0=DE-j`a!Q?W>gRTS2(Kn{<~>-hRDAiZ-lVrFEG?9H zP>yr8hXe!ZjDIRoj-~TxW~`D(j$Dzql0eBg>B*~-2)1?FK8vYdS;|0LXf~^v$-o@~SX-Goj} zh1=jwW?S!UkPNhK-CH<3f-#Dj(TnI^I`dC+?Z1Wo57)eHr|KWsy2IOE*lCm8{gyzi z9U{pnQ;>a#>7ID6CbW5FWO@*-eOo*tPZaC0YVF~>^klf2Fkrig;X<4aRPr|W?mpBD9PI&f*!yOx6k{YhwIsDYN5LN&ucLTv78g`PK4+H! zKpf;AE0Vqn+Z#~C^KN~g;XfGK>ajxX>P(6VjIdF-jP?9$%bh+`rsuF(T|sh+@W=x$ zcO&OH81xm8o4K8?=@9A=zskeS1Q2jJBN-V76;=~W_-EqB!CUz*=F}{v^W$8Xw_rD5 z^NfMV(-r99F?^aFb!e%cTj75V_=iQ&^;-#|nkfA3(ZsGcu)~XoZK36Q zeVMiKdo8Y)s0~f0Z?M|5Z2*rX<&Hx$0H@RIipG^n(v{YR(~UT*Jx`-_4~M=i)^)k{ z9~RmR4KZ!jJ2h#;NXmzkl3BMA)Z|vxBG<<&nYqX8MK8?1>~ww~@T%T2-CTlUMn5BGaP%YmJuBJ6 zP}Fc&XQ16kbls6)l?qfT`EsYH`4!nU%8x<|M0x$~%+korNh>KK$j(6QanK6msM|Xu zqBHLyfX9bW3I70A$FE+b6U|NRX%=n#I`EXb-m~`aFs-(p;z;H}f~Gdl2fsi4ek->L zhI4l~@ikSfeW?zIYS7z%XQB-{DA9~jfHoXw80>w!bg!VNOO){HH*=-7jx!{2LWN2J zfyW^G{{TwqMdb9j!%(#qoILcwJ7 z7zRKF(VuMQyy-<;?1Z#A-6~5+qPw?(;i0&A*x`s|C!7JEK=!R8B$bJrb-CbPC;LZ- z{7(Ayu-|8J40?^S=bdhp7Mjx`Lhczt^!e_(U%ml@1iehKvwnF6d z*q+~)72Anikw=k!X&%Yr*rwAK8|x*)+Z@~?4vO4y>%gxjy*a+ei+B&TN%ezc6J&xk;cJ>gqP z9g&5R^i|h}TTJljSS@!UwP*PWEs=uQAC7C8O*sRJ@=fb9T+SS;HsUu9K|OlL`FK00TbBvRD-f8h^{?>srD+f8e8BsbQO>_(Bk>at;!5zaBwJ-Dwc z5U$S3aXj|YRMk9Vsp^4Mjf70L?TlrZ?mQl~&pA6-^)S)p)X2F(s$9yqsH0;x2~GfG z(1Y%4H8zbZOPfQUJ{uO7GP1Y`0Bx$Q6ds`QP1S8`Tq#>q+dduY_jWVDvfraG%Az;U z-k|f)^shG)8=cTiqwTE=T+A`LvdTaNq*&mu=2-|5Lki`y z&mf)LdiAe4*5)^jCUaLdRyUThxYZ%Jj!ee{4KCTEXxuz)j-4_MbI%db>4h|p(ETRG zwQWw`D3zsHi4v&v^}rSIxEwoY+_!V+PY&rGY^h@@TX`cw5=X}>ysmzg^muH#bv_hL zOl2%OyqUxJo9r;(w5_bc840F*=IQrJ~sHh$4tDda% zw2)Y&k^GLV0A&XRf;wZ{v98kzyO}X+OB{;I%wi3-B;C6kxWjbE*0ScaIqJsfq2ue* zb)m^K$INSnBop$V<|-;P$#Jxg%wLJODQ|Z?vBs{ixPm#(Gs)?WYtE@Anb8x)EcJM< zZX-YHHn77N7(MoklZwyUYHpJ>C(~_p>86tE00W%MCf}PNaM{o1K<1p9k~E94$-l#U z>s!~l(JrO70OXbXqrWP8b)^*~%J*5@={gPNwYa*}^@5ROh+<5#%sPycI(>1PyWHoM z6xkL2v7lON7E2Yhx6c+>Pjx4l0XWFo4&Q9!>08sN)3FkwlF+O1Ugt=>@vnrhJU1jv zJVkA5YdevJLyf8*&=w&`?ewooF-+l|N3r+c?5Xg(Pqpzij=VI)ySvo%-S_@_jKv|B zZpG{h?IY{ct$S1;lDXqnsN1pn<>BkQ4K~_1R4u*0zz9doxEMTl>DsxmPX2+1rFL`v zDDftkZ0_x%yz}oR=gnSKN}Pow-}3EWIgYNDhtT0LuXEsk+7CjTU(s)x(%;K5MEfok z0a3gHaqXU?x9461nr!v`gR%I<@t4E0X=eHS#g0fp7wF?2Xl4%_k*Vm)8I`?pUXC7j zIO{^k&bHR5(=O>U=0KZ=LBY#@7_R9*bjE^CN3lZ%ow{0F?viU;sLVHkM;Pc>5uTlX zwdcxqXSC?4MEeWD+NP1?PYlCu^V_zoZE7twNR$El;JZYsKe-^}d*mAAsV5h7anz>b zd~xwh;NG>M-OYWbkL?Icv648K1ZB9uC!A;WuKYG8>df=%(>(9Po(ba|bavmC22Y=A40Zs&9*Wny?O516yeB}*#QT%}O>()bh3LT|opW_< z6~bI7O|74i@<}HqrAgR1Y*~f}w`i^foxDOB64ZuR9Y_S)Q&MhNq9q6jyQ&HI8Ir9ChU9BlOLDRyL#NXV&5A zD8&`^{W`}~(=K$VVBV9)%Q<1VgM-M=73V4HZs2}a{?}gxr5Z85v7K$z6-~$^Cn?F} zgMbg}YrhRr(md=;56SDlv}yO(7Hq?0QVCw893t{ipF%4N25y>Bh$1^QMCJn)U0k~(`5ifadQ(8Mo)3jj)xWI)sClX zN}|;5bw3#RnXN>RtV5~6CPa@UK)NtIaHqa{^!iqD(UUA9IBUIf=Kk0Q)ky+Evn9Ih zP|BloUE&W z*c@b`!5@Wl)rr=b?%oQqLki*+%V&MT`PV(vgUI!-Dx|s!EdRSTNd6=l(AD3P|OKVMb<<|CVt9hg?adkY2 zkLh1Yhn3HnuNyPW8bncd9I&H=AeVJ2y*7d~=rPv1(aNkzZdMeZeZ+D7 zseH|^5M=>6mGvh)ns*)1u>@%;vYOdro+z2(S6~1#Hy|pvV0jdrv=eBR?jnZh+g?TF z&ZP~-t0^cD_3FnzHB3aK-2E@oHA`4vid$s+T+)&zgC8p?19K zEa(I=ED%L6%A0Vw?4))c_2$irKlvTo^*hQ zBoR}r^UY!wA)LIyO{4{XoE9ty@_(lTc-2}2l>|>M2@Jl0bp^WW zT3a(8wp#$ojCzR^?4~n8@KygaUc9#vzS~NaJESAoo7Cl57==6X{orGDmA3 zw&vI)lHhTkmm3%v2r1jNyU|?S)xKgRz0@#9Xr#DWI1$0;P`iYb0i52 zTjeb35CY-Y5w*7W7#XhGP`S-jC8_$W`yc+#dS8e1h!OeX3CU<(CtSGdL z^V|lRSZ4+^j^B5jjyT7EQC?%;LuU;So<1me6641aUf)~Z7{$CTY+#=|BYa>Y;ZqyQB8u>4_{_**>z^{pz@>}f`c-&*Og%>+@~U3q5UZIL7gX_YWcXWtx;Ufhb| zl}&EW_{WuKP4;`MFrq;6+ejH@C+1vZ^{BgmUU7)X;ZQ8x+jKX2^5zeSt_G(3>%Z* zJP}+qDsvm2#o?$d#IcKVpvC}V2Mk64>E5^{qZ>!P*y%R+OA&V1;dt_ZCphjn;-hg~ z*SFJ3F#a`0JC%^DXRc}PT04y%)R|%^t(PYXMlwP4s)?0Ni(WR8p1*Nj8z=QZe;=F{9rc0Gr&%b7k+DM5c1F^@= zf;~a?6JNpvnO;jV5>j#Ysmz5p4>9Z%(4{MI*b zL)d;DS-bgi!7y1D@1tFr#N z8m4nHczPR`jQER0Hq+q$0L0SC6r&Ju9!S3F2mPEMYR}n?T^o@2HfZ7(Fo?AsH9;`X zZcga&)L?*PBhc20l3^;W>wG)#*}Os$RsKZp8{hWt8~KWEVIPn9L`17uTU_gl#9 z=jF-hNUuUNNoaA#9Oe&>e06Q+n+r+SOZc){*-l%JL6M(&=dC4U-oW8>zeDDm?;gu8 zx|)26B7L9@#~oN60QRpEq1j|=jmmnziqlTIRv@A`4ulY=Cj^Z8^{*cvMa7-i zbfk{j+r*YvRuRo1Rb`A6n>^u%PEISziY}}Q9s}{WhkRM6YI-f4@!X4Nk_*Hj705Us z9*6Ovy-pg`?Wywr0PPd-5@RLayQf=b8-`Ex(77;$IT%&+J&3NVb*!v$IO=|H>z)dV z+W!FlJ=09Pd0Aw90}}!_Zs6n+#PQINaa}R1bSDcKx~GON^w?sK-8}0n$iVwd8Ff-V zY&!KDPfp{tE_7(4p^t54b0{%iTsuh;@isw1r#(*`{cveqxI|gBi=>mw^4c;%C7DA8 z2cgIybBd)gxL9)OUuaRj!K1hzDP7rCGRw(KIVad#F3q{D14t`gO5+hS0v|ic%9Cl;pfaxE$LUl$smGM za(Nwoqw=g&i{?kN_*+O2+$Mj28DI%v^I-b)&(^u-xrb|>^`ylRi6bhqvW#u&!_(6= zqO2s2j?N~T#8O64dWGbGI*zpMVV&lcrs7T)Au@M#&mWnpiqwjaLQfWH%_f&25k`-& zhnE4!IO74hKaF}Ac6rscKQMkZi<2gzv)!9DgdZs$;x}hdIXfd@i;qlKyM|Y>;o@S? zjIUnD%7R04C)y@rTIXpS6r2*ue)k=PdeGBD%V>~8acKn8+RoRu@!$)ViGu9wl23dA zjwXM?(()U2 zGu!EkSJYRr`lmIw!woL#D3%s^*hlE3xneNUokHu@!mP+CA0m4552Ad}2ZOt~|GCCeGYY9Nz-rAna;0rs? zHYsCa3cfy2z~;85&mR=^J<@$HX<$`o#DK5L!{+9+lV_Hlnddskhg#uTB(x5}NO?+} zk=s3bR#G%f@=agi{C7TJXwK~L8FP+!$>i2f2FgbrFM+RYBh9_2k`@F!DV?V$uF`Ss zMwS|pzv0gW+sk_t&*xdr>w>x352~;k2lA?fE-A?)>mLF9Gtz9}7lJY8M!S$;4o_@~ z^k~wuJo>dycG2zh`zvu01G{lz#A6=Wu8Vd!#puZsFr&F6xzbp?*w#KltIUx`#IJ;72P!h&!K=i0paRg0*Z^)#qjn@ID| z9r#n?pT$2JSX%f`#1iP5PyvjQBDUrn?P9?3k55YG#L{)7ORY~2PgCg+4Ez-FWEw0w zW~<{lZ>539+v5?4t`i&`kH{n6(!A=JHw{lc=3MV%*}ffoFw#6C(j7L%EoYinlILRM ze2j9=-P>{Gob@%sQWgnU<~@^Lu!emy;@am;Tgcf+FqPae!=4XX$8!sxo}U_i0Qi1e zD~)#A8=Dx=mv~}Dz|V53GsaC^9hf8GEo;NqdIYD*x45~}NCGLslwe0W;FTcfoYu|U zu45j(z29pw<$@-an@Qb_Lp>)+JtLqe2cOfgJ8%H@VcCX z>`&)hwIO2p?s`6%rlri07KA_)XL;p%V;6s}Yrr>W?6#SR`nnOq>6GxGDuC$2fD zaW_Y**;^tsW*wXH^C$4J_dTdlxhGer*>8|6j!>KsxB!lQd(&^AHhM;#r@UyOI>wFA zw|~o;xE$3aW_a4iQIA5peLfi{m&+ymwOJQ|#}3LrTJ55&aZX3%x5gbiRKC@G+qi=H zL6I&Qp-}sdf4t-nMh*e%UhWo3$CHRnpDx~67z~b;Vw zvn*2?Aa5}tw=sp0_OgMna1hP?0I!YJQRU6Tq6zv#G7JNgdXo41Q!& zwD+Q)k*xqM(uJkwEDRd5}iYNx2-3qZm0~=gnLZyJZbd>RUBC#_gZIgx~^KsbEOx zeJZ5^Ugrm?YIg&1M*=gJ+O4&Qe?C2pV%3U_Zh7vps-i^8JgpiL(Xx8?5u|3%Ili^LK#{>b$`laq9E6PiHIE^;G3h@I^eJ!eQd_x9=!~b!kPM#PO?A+w zb62TkeLEGLR@TNiP)4Hz3xEgt73jrS^PH|!xSlH}j@>zF@>O%rJ*o0srKz8BsVJB1 zvmCqs0IR8SG=goO4ddSuT7uu-+}>I!u&)yeOx1(L4RVC( zPZiPUFctxU9Asc;HR0B$sp!FkTJEO=GQH!j<>V;mAbMxDaXNN1+^YB1dgZjxYB5J9 z;7CRQpEUeW_#xq66lmAc+OOG^A!4zUw2t5o)U`#$pPXJG_!S3)?xmAU z)gIb-OENp~Gs(#S5yiE3{lAq?dVZo?xCuBRFLiXBTK#aQp{ zw09`Ws9LMK{ISju1|S|VRCV_vu#}z3QY{Y(MR76mCYm5XQy%sxK|Bc%bo!6Rlaz>Z zIt?qrS9ZIiz27a8jKU8u82RSsa$>N+Nw zEQ%O`$m0Wn>}f^an9p<4w9Pu@*;QlS6?*MFe=6NX<(oSj?K0jyG1l#tB?@wL-yLz@ zx?!QoQJGEANDCoF?GRk?!r%Lqj)huyUKRbL?Gu#)q zn(|#v?s7o8`y*PUiof*D!C}|EdemDyy0$#BStO3#;dso@!rNt$pK3;iyS115Q+B~`Z+3|(Vno}7XDXzx&G#7p09vL7j16LM6qI?I*@8H=z)g?TggoTr zb>r5vld$5C=nuf&6R^zMX@v!8O zHu5v|^{b3cFQL-PvIv&qXp_mv`64)G7$IFVfKOcW?Oid6jH+}vZEEda(90XigQk;ik> zKD<{YMp8Wb<6lq$+uCj<;5Xmr*X08PKDEawU6&_xeFgBcS?-+~%SO?V*vCwOeuML_ z$|sGBN8NrJf_Y$tghb>IoSbuxzy7N9;ExKbvDHha&Y^;U+lD|a$1V6`n?_1!ocNDQ zzhq-0N^y{>laI*exvE6k4KvK|?MPfDzs#ftW;hr=q<0mHM?z<%cm%<2rCF1Ha99F5 z{e3IaqK<0L==Ix~QV3c={{SgmE`7Q0U5Mam+~9Auv-Y)lBmLxgFb;9Fb#LiR+9>hg z6nMK)zM5MdF5YX4`3r&&6SY^|bUpt73eHKhx{MOs^PO+u*NZhcmTwU2D{Qw4TG9Zd zmLz0+*gbpkT=gj5bJe9*D`V$R8GH<}iGJOF(o1yM3i2~H(hm)j&MV5TOOc+w9}}gD zntrY0p8$(>Ks5_XS5XX7^4>}Q>tN&&!20`EajfDx)FV?<(6q0Lnl`(7mp1oP=-2*f zg61Ghax8#uDna3c4ngPn)YPpR9E%R%&d*P|xPw`Hs5K?HwV8K9u1ZRB2`Wf9`Wz2> z^6RU+o5fh|;@34eCw0EDX)WC09y7S$;N8f^_We3#=N2Iw)|%WHLiKG_|Oz07=} z^<`xZgU2<<nJ3e=1l0i~%19-_9Sbx&kNxzN04JO=)uXD)SLYcz!|0VtK9U zJD5FB&ac`62%g^Yw4D{Bm4MwXytcV28|Evx`}3Y_zJf+IA#{FK_||<>`%2~&yp0y= zJh|-H%nB=>Z~)p!+sOxmUhN%^9<&-~o1{y=<`#6k^Hl9zFjC;>3z3YI`PS&clx^jX z-R*9L$}Bd!gTRPR1~5lZK_fg0ZIIb!=gAgv&u=`79MdJU!6*v(Q-P4bFbn`Znw`d( z{U^1%*jXc~0zd&QMsj^~Tg7s#pHnBO>mV;?mP7%3lepw%2skBA*Qc?rntG8bSh=Wc zmbP|=%XVW~Jjkt|vk$(C{Xrw4u8w4mbr&XhKZ<-w9-TeU_FVGIV{%KhPI6VV_lKd# z!Tjrrty>**>9fW4JznPUkq%Dd`@l{LA9K>Y`jrl)3mgWcdv9*uUG%1G@@CSp{c0{$mWR^+01WjAW4pJ4>iaYN zi?JJdQ`BT3^VQkwG1|LE12Bp|%ai)k zY~#MCJ+A1>EH1GlOnS3=eE|I`8o8`xW9PpSX>(d$VgZ&MIb*;bc&$rVu(2F?bWX~n>X0fV8C8exZ zMUw76DJ27y0OaS_{F)q%so2%<#*rO_5Zj21m-o`{xxZj~oMm&=0al8YOKf%e$Asq8 z;s9JTECb1gQGtTI@}u(nswyI(UzGXd#C{#TgY6ap1CKVYV)g7 zx#?l?N1Vx^H`%otDbsYeC17P?(l$Rc0C>iFdSl;@CapeG(}pJJjCiZTQO>en*(xD} z=SkxENMvjs!>Azj{A+?qqoy@eIK3OhdcTJCt2+&B%C_n@THc;OJGhPc?m8a$u6Els z(WBpO{70zIFlfn^7=~in*vJ4L577R#l%aDcBhxf*5$QUWv0ImCvy|+*v?puFAOq)( zheM8i4N8eAoekBMylcDrW>aoJbe}twqhp0<9k6&l{c0Rd6s~;p;>!z5JImy`U$trT zNL?qlCDC_(7nhO8Je44idgGeZ-X}YzczqGp_eQ-QL`Qnc&Te5}XFN?FJ8l^FqBrPS zYsA{+mAYHU;!O_b2bG7D;!QP|b`!@`0A-vJ+ai@nrml?Rdz0yNLp9IYb#D*8jd14)eP;3^h8;J@ z^I#9}CQsp9@t<>{D;}Yx=yKc$A-~*5`d;qxnTq(-M&LoL9F(riYtdYIt_38$)jG3rfpvC|C17QpH#jySX47bpzVF7N-L;{{VMA zsFoIMS*~}@wLz0;UR4xe^d7&B79zu8xiVcs^Fb`oJFe6Y23>ZmGbrhif(2O7{VMpY zQ%e9W-S#rB;-{(awEagyJJ$1dN7K_>%;j{?5yFi$LoFbT`A0Z1!u*hZ$8V)nBvndg z4x_3zrJHi(?L&YM%*&sZv+B6({xxmfn66ZK_OTJRmPfgt0oeJ`9z%B|5ArL9qdFry zo>#1D(yW3zP0$oLEI4OVoB@uQ_O5BY4I*&&Z47MJ7uNtY0^UhEEw`{8O>!HeeJ)## zNU8D#hMrCgomxf5I5-#|Ob=3Op$5)svT2_|{4k0LuC0?ww1Q75#wKrFQhgq&n`y;1Di zPQ9nfo9-0^asKWkd~<=<>0W}J(Zf=nrsL^)Cbqdq;%AEm@CI_jwt5bxRV8#wk>cMJbjy2-^CT(d z&1n<)dEjox%Y*t>Ggn7u8cgu(#WTrlw=0QQ5$BGMj!spG>%km!uQIGpRuZ}9EbVT$ zT7Al3&i-wj{lPg$1RkM)IThzsf;!<);`~eDmA|xPl?0M(<%rKtGCjerSyMWpS(siQ z{?gFrhQ|4%n%@T#9OXv=ex|XM4JA9H-n6)_ZZw3xFh?A)+$?uHM-LpKnOyhbf&2-o z_E$z+`jTrl@#%3|LMN3p+sMt%mv)7j;&YUiG1;~dL&kpa1GyE?Ds0-6&pNvB#nrXc zHxk?!Lk~JBpnS)%`B#XZvA1lGPoSTASN%^e+%YBS&?@YBp$+B&biy^4q`erw682YkTId&7f@DweVyy!zJyS zTb(L$vE9vYzH0{uqFlh=y|+2!XFE?rPBE~(qB|Q83tVYlP*0xC)l6_q!emu$m_K!a z{uf@o@Nz0DLroClQtb2{Cr({}!h#h)F@Ws;kIT<^5|NmK|7Vn{aSVvug@ z*9QT@7d_~M^u<(NnKnHuOVLD%g$I;XbL7j0T>BsKs*^@@XK8O~`;L<2c3}1Db15SpD_*qpu?Ba!+qDXyZFF4nAD{;giQa;QkesCZkOH z{2VTiF0t25#ISz<0LzjV-xD6O=Ypj7T=maP{xvk~n^%pIbHpAe`x-69pb}h00J@4k zNFzC6+auGst>szRkVznxJ&u1$+7mIY6qcvfpAEEy)7}YMSGc<%5fK{-dN2)> zf!9Bf#d66l4H>&302~jaoN8hPIGN8jwdL(-cV@T}dQ` zTMXIbrAlDpb9%m?9Feh(ADMx=62N@Efbm&Whg5Y!XPZlN zac;TE3IPCT1m~x(ddJ$d&AD!kEi1;?x?^NH3xl-@>PI})#}VAlR1x0zcgLpb}20E)H@!^%b*`&f#N%@pp#qb(eRIF(Ri! z?lIf3s%q%golaB6F1#OgX&XavZ@ptc5>PV0fsA9fAIiDsMC^rQ&voAi$#8AiVj@UT zeAvg&%X3^6aO~=*T<7lmFLGHOQ+ld%kbe+C_pV7&XG|-jCA=iA=X79@ryUQ=)PwZ> zD;d%@Rjze5x*S&8b;9f-KQ7#D&+#E+l0Cs9vv9I2oRuOM+IFR*GH+y!wGA~~@>(Sx zbZd}KULl@4psequhjz6&OL!o7(?Znd5!uM>`Yx>8i%F#F7?1g5DFb-^5(ADw&oeaU zwx=bicwC#St82Swg7V%%w-&&Rq<{cQj)Wg$&rw*;nb8WjH8iUUtzs}@JIf-#OKUpr zP=1|M@zfA&HmqBn&eu%QTFOP#v^SD7f@igCJdr8try~DkMBt*689X*H!1q^P&Fkyhu&9kL zb`~}QHUk5p1zY)au4SQ0S{*bB*5DOh1_J9HqIfrWFZ**!>1m#r9B5@ z^AF<&hvKU{+q=2o(`B($D>gR?7oJNL3VL+Le*<2P30<5u;(P<*h~C#yc81$v4po>W zib(`ul0hJ2t$S2fhm}=XoZaoM+oa7ANbb?R#sR=3cwjisY#P}+85!2MbFI_^QNWT- zsSJ$8fjJn-8O{y}=~msu+50o%T~19_M}5Vla8hW?WF9i79)wq&RM`Wd^Nmwp zZ5d-KcQwIQGOl}Zo_Pn3Jv)lzl}=LqiHIowV+4@UO~f@^A3)QEUz z0;ZvDHGr1qO&(O2_%fsAqxxg1!To)zr9M)iuc7A}uZwLheCvHZaj7Z)07-W_`LU8g z=;!nv^qqYT%S~u{&Xks(8xdN> z%Py&K6VJH7`8m!=_w2umXQg(+7Cf5uF3+XD8qSS-1n)J)^s>6MIB|^j&N(>7E4G}p zJWNE=KSKNqbbP3HL}HBKsxUbub^Pn9Cy`c1(0X*Sl~ym2kEa!@*x_$eZ_FKtBD1kd zNRCN1sUTXr600EhJ@> z9u-dkNc0%4>NUHZb*Ub!W#gSP>EVT#8&lu4yttyQvBXW6U1Ws(*_Bge(VAWALCrIi|lkp zcQO<0HkTH+R`%xMtYi{8V-BM|K7?c+t}C07-sbA2gc`SpBw6law*{>Oth!vp{p)!^ zbV7ZB0;W_=BO-fkGHq7d%VjOCX)Cr6!}pgK(F6OY=u5;oL)|jJ!Yc{J$h7P%T3bHZ z8b2#1JI4c&*}tV@DBT(e%AFWGQH0C>tWKb3<$wmWcchAj^iy`zKk5NmMnMk~0%PCMp1GS5FQ|N!k zy=Lh#sgtx)70CIvBM0q~DZ8IdLUve^>E9WDQ%sYD;PE8i}J`?!+1)h~-KB;#N zt;F%}5etX%;cu4(TP?`^4SE<@^Bk35Q}TPq9wD~8)Z&)y;`=?uPucArLmW~s45-|E zyyvBT1t?h_Mj}^dHKbYDiD9*}w`+*+1DPF;a>Js9W5)xZTG^wRyDZ6XG*Bh7$gsEs zG8SZFdZ--(mgyEFH8j3JObb-IY)U_)TzDUPv|&||K7J$Pn7S!P7wu)tDi9F9R;sU27 ziyynwu21+@3AWAd(c9^^v-onw9y<|ntX?irACnTVQ@4V28v*$PA?Ofs;*&r!#0eihpj&6(?(P3(aq1%`3XPHNM+gNfJMNaO(JSh3)P z#WNQY)0NIUjxs%IB2GtLGZj8YP_JJ3p`xJAGP#0ZHI`G1wsX{b^H@o0btiL~)GYU_ zZC+0sx@YJ;s|hQc9JID@MY$tD(hzqs9S^l)<6}g~V2na$W;te1cO3RSV0wyN)+y>* zv{r`T-MgL2L#{LP9>iz-n$i_4LxzW2r}(bw+C-LF46M>SbJrLEexkbJi8`ellPQnsm|zy7K{xiMT=3f zn)wrM9H2sYWITX-aC(3B>kd@SBP$$kqhyfEEiNE30V_!l7+|hGbq)9e2d#5XDLqcg zaw^;D7LrR9%rA-U7{zx7Rgxe^*5|MUXSm4p&1B$>`H3$q86Ms3R7$Z4EiY^sXL2KM zM@;a3R~&nBS-2LaMJ9t4{O~*z3v1YRyfT7S!zl%M?}9k)JJwUAnQ^FSNvF>bmp)*R z?QF?1O1q#Fj!J?#K>b%eIUTE>bd*h_HZ^S{^LCv!eLn3uk`=?D8R3^dd41H@E|IE{ z(^zTCcOD~=M3~*Ncw$HUC;V#{Psna)(J@@aSI(5HE;hTV86C612af*$okXEw##c2h zn7+kvh67;0#^ugHJ-&yvLRZ|Ri>qxOcln2$k>Y$H%H}1jXW5h z9iLM}8$8x>ZB&pZ){OkEA|!0t$rrT;8#(TD7ScmA+4+c8UoAx8&)y}8!9p-_M+d)CQE<8ThQ0=%ts3ywfE#H5 zBxG}yZ*%%r$~JzQsv{dmwtJvuyKf~evd+BVl^`E|r~d%eS54iG&#|TB4MnW&Ei_v^ zM-f3h?Tx-;jNwi?4CI07itC$66AE0~v&pZI@5RDIRo5qAJvit`O6N_pr`eb(ZBDR8ioRy`~8hU=OCGMj=-PBS?B)q5$!4w04pdK-fDxBHD zU1)oUgQ3^X`7nDdJ-Y1Yj!BN_}Xv*yID?1;c-Uia+wbS4)Zy%c5a#VCDp&h>} z_Gv`&YqQ@puPuDEI2{L04;bSW(3Or>u6J;*)!>{3`HA$aF=***E>6L}obWz_>%|6c zCj4X--Mlxc`uk94VvLMuVxm3EoM#@r4l2LQj8@7h$rv|Uj)xV)CF?|nLSvp}V19HPzF~~y z0g!u+qrG7}T-p(AhFwp?laDTaM9BooBQJxwNc*`z?2(l|oem9iRI$*LM6uu7*~|T! z_mRwF$CC`qFja=&@v-Cv>*-h;BK$I2B+BgWlYmRQl@pd$zFLquVfYHnj;$MT?kb92D z^QdyUN*zfgvr?yX;Deu=pd*ZAb6847v1WAE(S-ROmHX{&!|?U28D}qi%o*}SCs8TvF%a6j7n|c)m%5if|<;^X;xdgTsZ*iWZ9s5<&Ou0)!=ZGSg zO|h`itlSAD+jDrEwugL@quY{C;47z8jwY_zx8Wt#LZ&R_o*ac@&AAnis6M@Ne;Utr zdHA^>TKqe@n9pD_&!oQ8z7a;B2x!QMwku zz#i23fgiiaVnv~st;D~=-KXp8Z=n`t9GF~?fMq>h*-$n-xFXDb_M$45|$4q2({A#_DV5ZT*YT9+(n!lA6 z(%c328qnDuowz5 z7X*5qc=V`PtCr}rXKFtX-U&4W1OZ*6eWkwc3g7|w9N^M;fK7b49Haas2fgt){7CKdlZj9o5Z)~>Pxe7WRm2Dx{dh~5z`~zud(D;H0w6a zqXcj1_flOjRoxR5=ozp$&*4(!*;cXLTU~v#N;cE6ntd~CD=|BbyEaDC*Y|93^gh%r zP$NT3xsuV$@LbFQ<)a@mjEv*26rIpW^c_FMFkNwTDn%&(WyW_8=g0Zxvy^T)9nF;J z>XIuY@Z>blDlLCXZ(ujr1deVu6|McY4A>=r)qaEqxfD3 zt&Zsg(fM&qIouheJ8(fC!a#WWXd=3E$MxcTNWkWbEe&rXEk*Q}Z5 zwQ}{Hv%S+BX?&out6WVZ6!Sv3&JQH|_2P!dvG*+3l3f;xA^V8%%BO-?vky-|E97o| zq@pY<<}0a9-@9$3k)7B+-rQ4)6Fk!orQJMv%oE5}Q1U~OyERTWG>YcbY<6v_YPK+i zKtzUF8Gc{&Sz-=)^sT5pMOEl?_qvnn8lCmrU>5V)BL^c35!es@J6hD0&P6LD)w~lV zuBxus5`e89&_jZFKTvq)vQpIYu`g5WPXwfB@jPc~Y%Ak|$l&7@=+KjB@+(VI>R$}I zvJQ8)2X3S4eXG%fY~Y#fT0(~TcJtq!oO6%Pw~5Opcd$Ug0pG$5j8>ec65Q9fihY2y zg1_GSb>gWZ9Ryn!X_c9eP@=6O2=65&ijaJ@=L7sHg|2cMoa(bIYZCdG%Q5uzKT3&8 z$hf3)QmxAGXv}el!7RjX=RW?G&nYs}Ia}}aoyulAi97*?Cb65)-Z~t^DnTMf;C!-q zfQ<5e#bb1fOz*TkS5|Wx!FA;ZC9=crj^Jat{ISJtN^O|T^t(tuwQQPMaN9Q>#0;Lp z`qy%bvCYq^!fTqfhK#a90)M2q`3MJS&rUI1HSD%JX{OH+@g@D_mbWuPR#`X_#xlJQ zdYlgR=2dT@-%TWQF~M+j`8@11s0_+6wEB1L(AOlBI%8{?G2L8Rv9)JuZO_kcjB~&l z+J2s28$n4o<_Ial(QyMm?&`+(;&0D@k837?$L_f4Yf)N2lJdh`S>$r!OO@ zpUMLgMCvjJW6x7r?#&!eMex^AiWKBRL_!@1sRvFY-00?YDpt;5WKey;{-OOCq~;6UMyOu^Ilx@Ti{Wu^V z4^E$2-WnKBL-VKOmE_u;weFJ@h0d)rw3)Y>c;j5DINgGv0gl9zUalPSaV<0R`%<(= zwPtulmCc(=0fj(fsUOT3Hs%EU*c{ih2chM(X4=a-x7wM8$Tqy7e-Z+!(f&LP{{TwT INf6op*?2?9?EnA( literal 0 HcmV?d00001 diff --git a/demo/img/sophie.jpeg b/demo/img/sophie.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..0365932eb41af19f4d31fc09876e4d3d964ae837 GIT binary patch literal 4373 zcmbW2XH*kRm&X$liu52Iq)LrQ?*T*}Kv1M8ReBLf=r!~zAiaZ>fbmnLBgt@661d>(AF~0BTJ&4K)A|2mkQ4m$#2E($7C4@>NuH%AMa3nhW#tu>RgF!} zEv;?s9i4+i!y}{UvGIwS*}3_J#m`I2>zIwrt?iv%>>lpN&y&-$bNsL0f4P7F(7&;6 z;=jTE2N&dqivSD;fr90UOqa*7hsDC-hix!>jz3nQU@nDX}Bz%6cZy<<9S zk7-i+yAta>xW8!sBKzNgh5x_E{tN8Cxt0OsAmGj6fgk`Sz@>Vs4TP`Z5J}MeZJ52; zJ~U9YCSUqF?oNKoV4i47|369x(#rUpLzp(VO5vWEz`$c)tJ7t~4=RlJ_n-KJ=Z;?j z-WX-V&g+Hm#32#J?5ZhSx*u}m^J{`T@gbxB(y_JlJ8JXJlJY*Aj~&G(`f}1q- z)#WX5D0J+5itNGG1mk?;B+7+B)w!s5>I*ydJxD4vRgwq(wn>s&^W}$Of|(Q}?nddb^GGT%{Kk6f{0rph%k1LSDpSr{)WGu_)3|ErdGnXjE zJCsUovM^@;&SU#iV)(V{5%rhI#gU_=6r}L*t@R6I9kT-piE?&cKM=d-?iDlg%mPxy z#6tu1QY`BwzpRnGsFgm8TmbS#$MEyvHRIVQdP^>I*a8m3J{sQ5FFYLaKr`^gcqM6V zrLTwTqYl`$?ki8hlN&&?6-;9~0#P0e_eA7v6N57j%QB-!N=(Ko$a6gyZT1ioS9gPF zgNg7jQ`JMN(cXdiPBjCW4}vIH8Lq&pf$uhy@cb)VE8kmDte<8kzOn{29*iFLtuV3I zdd!c^los1pM!y#|%9T-3IZDqrZnxu}V@8SRo!2M!g04OV3*)}Ua3o$GLbLe>zAys- z*pZ+Jr*B>3j5gu$3TrxVWJ+THeE+0cRg>KvpU*2;=>|90m~n`xMM@uwgl8%8y-8#x zc+3rYdZj(u<#7>-;L>Ce#c|gI zsa`-_plxoezC7A#=a=Ef$(8$B%u3p+@o+hBx>?2I%fxGd;}QOmbK$X4oC{d)yJ&igv@UBv;{bNJ+HRs19*^ruiq+6A)2$1y}plqJu z8Wdthg5X`^s%MK{?sSA2p4AMoJj*3*I9Wy4?3rY=7T8Npe!#kdRXn?+f$Ft^A-ET3 zVe^W7ds#Wek-PyE^j|Y_buIdoDlC+ba^g0QV*Z3+DEKZEHMrYmZw-fkf^1U`G#yQP zS`cG-Q zElsA^TEv(21UnhTg8Md@#T@iK9ulMQ&YT!gtW~iu`U1_u;6qAF`KvxF4(=lCd8TBq zyk3M!eRT2djOKW9a#*BpO5Q(yC2<-~}31kr~>(jq>c)C*h|UNNiUhzGJ_-eG>w3NwLZ(USY#=3d5P zH9!L}br7_%R8n8230-XBB`BD@!X9TXc1$;aG%Tc~id>fE=`dP~*#O)$qUwDr8oX|x zG-ZmFvkU0}O+sPNHrnLWBCZeMRD_ER=4@^q*JDiCPeueuJa%?cc9-lsvexM<4cs5( zpDaEq&wtu%qw9h^iVCJJtMtgJYYtyaI`!EMtTx+lz(Rf*`b@W3u8|(xexikX9^j@F z_0F4dn5MH4(^?)Kug%u0So#d&HUBHv)ZK(W$66Ky;!0sjiJfoIngN-yedNnOtz_;r zK$V9US}q#fl*N-*$kHX0)uBhc{XK}t3QS718+y9i#Jsi1Ucg&jDTd(_o})bBs@`OAeMF;%i@d6YN`^m_^pX_cf zeXM;JgJ<$mtMIC+_XGuDE)3>s7bdMKX!1Lb%(RC>z(ecrAp$Y?lExHprnmvs zxorjiH>VCdXO8(#qf5~xSlo+IsUm(ICDPgb&J_P=nLWFuv_(m;^Gao9Mdw*6?uiL% z+T=k-;p2jEDe7-8vU%dg+8DV@{i6D4&Dk3}Y`Ho96q23?{nkpXo(S??}`4_1M|#i0z*nYd?hk z>Ysht+tSgJBZSj(=1)V)jDPg}ZFn^G{Y&i%K5NZ2Lh|uo@U$YTw2jRuTwN){SFbRv#`GBJvXqqX{k{R6iDf6~D^X<#!N9*1CRk{0>BuZT>q4EaAxjWc4 zk+kzgrjts$m+gk%#nVvRRjL4M-3Hxuj`+na0dqqIl!a|g7kk#K^kr^0qU!2X>hAF_ z!-4bt!uy$LP-EuXEHX}+AW;0`9{=>ltOSMplSnI}LZi@AfPRng6NK3e)XOaP!N4f| z@wQP>s{I&;o8YfpSy_V}Nvi0%yn|(BteJXrvr$A!Mjb+ZKBRfWKyBa6678lu;tziK zvm@;2hBR0whQta$nvMigR6$x1hgbKt>O=-RF?Y=*vuPpD3;-(hH%Z+npA8 z-AJh_|MKT2@9nn4*liCbPMGvH0KA7!s|bAH4Aq^{YE8N6(uze}|7bHF%5LH;s#eL5 zOZy^W!etJv{Ul!dUSXtOGW%w?*$WaiHe^^y<0}D)g&yJtD+?v%?<>McuqHm*=>+fW zx{Zv8xay6*MnNNz5i;Z7R5X*FJ&oqUm<$csNlw}A3`FzB9n*s04wNu4TueQ6x-eJ) z$W&KzQgdK3F3Ca`XZ%2P;uY0~@tk2of@T~`0z=CGoU+u@wZGzhLNn35N7_z}g1FR$2(C9Lh5 z&;YQq8kXV_&lX+nwVPkmxTj1>&IUO6r4`G0z|{?d{LUQbJ*3(K=LUBrI1)Wgr{WGL zyKx8XB71PCg2QF@=2>N@%LkokiByq4zL@zL*1&c5f$i4bJNR_O*eiBF#wl~?P_W3j zZ&0NwMFn4g2Vnqve*yVaG18B1ElnbC^S1$QIiEiI?Ws|fgu~kNPE_NY&kBxMl&99H zOu0}1IUa#))+s*aSCO;K?hh|=UC43{YhjcwMY=&8G z0Lb+zo@utubJ}L8VMJKkYw{(|q!KjlromR1m@gjYQ2l}z_;g1Mw<;Z{o9r=r55~Bx zv(j7inSZIkW--%^3w9-+piA9Rg3}yxUk(;_>;^B7WhVXR9h?0>-%}}m_J*Ar(FeBB zo&WmeiO@D%#A;8#y7u>r(j~_1@?1VWjq{Vb;*sAES2a5B(=$bzyCFL8&XSoaPPLND zuu#v{cFw5gx~Wg_9g*rNcb|^ktDAe4^s0u&RezNS>{x`TCik9urrkr9Kfk?7&IXlZIcT^rU~Ox( z(C+j3=4qxK`A0yii+9@~YT7+@#ia7#MYie>MJow*!ups~)y_;FQT0Fi`%(s?*t7TK zDh|4_5-U;^f=ia+3NcD@-2e{v7lV+*iiuXc%l-$sQnPLYzGq9#D z#X(xTla=g3fe#v@G{|QksDy>@J(^mB#>}?F)H0=hZI|7Bida;a9=|R2eQm@n261&Wkz)f2HiPTH9M%hLc hNc_a7GIYd;$0lsNp`R8QOC{0rkd(hDROx!@KLERZEdl@l literal 0 HcmV?d00001 diff --git a/demo/infinite.html b/demo/infinite.html deleted file mode 100644 index 55fa09f..0000000 --- a/demo/infinite.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - Fork me on GitHub - -
      -
    • - Infinite angular-carousel demo

      -

      -


      -
      -
      -
      -
      -
    • -
    - - - - - - - - - - - - diff --git a/demo/infinite2.html b/demo/infinite2.html deleted file mode 100644 index e997316..0000000 --- a/demo/infinite2.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - Fork me on GitHub - -
    -
    - Infinite angular-carousel demo

    -

    -


    -
    -
    -
    -
    -
    - - - - - - - - - - - - - diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css new file mode 100644 index 0000000..35b2776 --- /dev/null +++ b/dist/angular-carousel.css @@ -0,0 +1,27 @@ +/* +generic styles applied to any carousel +use autoprefixer to build the final CSS +*/ +.rn-carousel-container { + overflow: hidden; +} +.rn-carousel-slides { + position: relative; + white-space: nowrap; + overflow: visible; + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + padding: 0; + margin: 0; +} +.rn-carousel-slide { + white-space: normal; + vertical-align:top; + display: inline-block; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; +} diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 43da3dc..dc7ee26 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.0.9 - 2013-10-11 + * @version v0.0.9 - 2014-01-05 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -8,18 +8,14 @@ /*global angular */ /* -Angular touch carousel with CSS GPU accel and slide buffering/cycling +Angular touch carousel with CSS GPU accel and slide buffering http://github.com/revolunet/angular-carousel -TODO : - - skip initial animation - - add/remove ngRepeat collection - - prev/next cbs - - cycle + no initial index ? (is -1 and has bug) - - cycle + indicator */ -angular.module('angular-carousel', ['ngMobile']); +angular.module('angular-carousel', [ + 'ngTouch' +]); angular.module('angular-carousel') @@ -37,619 +33,358 @@ angular.module('angular-carousel') }; }]); -angular.module('angular-carousel') - -.directive('rnCarouselInfinite', ['$parse', '$compile', function($parse, $compile) { - return { - restrict: 'EA', - transclude: true, - replace: true, - scope: true, - template: '
    ', - compile: function(tElement, tAttrs, linker) { - var repeatExpr = tAttrs.rnCarouselCurrent + ' in items'; - tElement.children('li').attr('ng-repeat', repeatExpr); - return function(scope, iElement, iAttrs) { - // wrap the original content in a real rn-carousel - scope.items = [$parse(iAttrs.rnCarouselCurrent)(scope)]; - scope.$watchCollection('carouselCollection.position', function(newValue) { - // assign the new item to the parent scope - $parse(iAttrs.rnCarouselCurrent).assign(scope.$parent, scope.items[newValue]); - }); - }; - } - }; -}]); +(function() { + "use strict"; + + angular.module('angular-carousel') + + .directive('rnCarousel', ['$swipe', '$window', '$document', '$parse', function($swipe, $window, $document, $parse) { + // internal ids to allow multiple instances + var carouselId = 0, + // used to compute the sliding speed + timeConstant = 75, + // in container % how much we need to drag to trigger the slide change + moveTreshold = 0.05, + // in absolute pixels, at which distance the slide stick to the edge on release + rubberTreshold = 3; + + return { + restrict: 'A', + scope: true, + compile: function(tElement, tAttributes) { + // use the compile phase to customize the DOM + var firstChildAttributes = tElement.children()[0].attributes, + isRepeatBased = false, + isBuffered = false, + slidesCount = 0, + isIndexBound = false, + repeatItem, + repeatCollection; + + // add CSS classes + tElement.addClass('rn-carousel-slides'); + tElement.children().addClass('rn-carousel-slide'); + + // try to find an ngRepeat expression + // at this point, the attributes are not yet normalized so we need to try various syntax + ['ng-repeat', 'data-ng-repeat', 'x-ng-repeat'].every(function(attr) { + var repeatAttribute = firstChildAttributes[attr]; + if (angular.isDefined(repeatAttribute)) { + // ngRepeat regexp extracted from angular 1.2.7 src + var exprMatch = repeatAttribute.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/), + trackProperty = exprMatch[3]; + + repeatItem = exprMatch[1]; + repeatCollection = exprMatch[2]; + + if (repeatItem) { + if (angular.isDefined(tAttributes['rnCarouselBuffered'])) { + // update the current ngRepeat expression and add a slice operator if buffered + isBuffered = true; + repeatAttribute.value = repeatItem + ' in ' + repeatCollection + '|carouselSlice:carouselBufferIndex:carouselBufferSize'; + if (trackProperty) { + repeatAttribute.value += ' track by ' + trackProperty; + } + } + isRepeatBased = true; + return false; + } + } + return true; + }); + if (!isRepeatBased) { + // basic template based carousel + var liChilds = tElement.children(); + slidesCount = tElement.children().length; + } -angular.module('angular-carousel') + return function(scope, iElement, iAttributes) { + + carouselId++; + + var containerWidth, + transformProperty, + pressed, + startX, + amplitude, + offset = 0, + destination, + // javascript based animation easing + timestamp; + + // add a wrapper div that will hide the overflow + var carousel = iElement.wrap(""), + container = carousel.parent(); + + scope.carouselBufferIndex = 0; + scope.carouselBufferSize = 5; + scope.carouselIndex = 0; + + // handle index databinding + if (iAttributes.rnCarouselIndex) { + var indexModel = $parse(iAttributes.rnCarouselIndex); + if (angular.isFunction(indexModel.assign)) { + /* check if this property is assignable then watch it */ + scope.$watch('carouselIndex', function(newValue) { + indexModel.assign(scope.$parent, newValue); + }); + scope.carouselIndex = indexModel(scope); + scope.$parent.$watch(indexModel, function(newValue, oldValue) { + if (newValue!==undefined) { + // todo: ensure valid + goToSlide(newValue, true); + } + }); + isIndexBound = true; + } else if (!isNaN(iAttributes.rnCarouselIndex)) { + /* if user just set an initial number, set it */ + scope.carouselIndex = parseInt(iAttributes.rnCarouselIndex, 10); + } + } + + // watch the given collection + if (isRepeatBased) { + scope.$watchCollection(repeatCollection, function(newValue, oldValue) { + //console.log('collection updated', repeatCollection, arguments); + slidesCount = newValue.length; + if (!containerWidth) updateContainerWidth(); + goToSlide(scope.carouselIndex); + }); + } else { + updateContainerWidth(); + } + + function getCarouselWidth() { + // container.css('width', 'auto'); + var slides = carousel.children(); + if (slides.length === 0) { + containerWidth = carousel[0].getBoundingClientRect().width; + } else { + containerWidth = slides[0].getBoundingClientRect().width; + } + //console.log('getCarouselWidth', containerWidth); + return containerWidth; + } + + function updateContainerWidth() { + // force the carousel container width to match the first slide width + container.css('width', getCarouselWidth() + 'px'); + } + + function scroll(x) { + // use CSS 3D transform to move the carousel + //console.log('scroll', x, 'index', scope.carouselIndex); + if (isNaN(x)) { + x = scope.carouselIndex * containerWidth; + } + + offset = x; + var move = -Math.round(offset); + move += (scope.carouselBufferIndex * containerWidth); + carousel[0].style[transformProperty] = 'translate3d(' + move + 'px, 0, 0)'; + } + + function autoScroll() { + // scroll smoothly to "destination" until we reach it + // using requestAnimationFrame + var elapsed, delta; + + if (amplitude) { + elapsed = Date.now() - timestamp; + delta = amplitude * Math.exp(-elapsed / timeConstant); + if (delta > rubberTreshold || delta < -rubberTreshold) { + scroll(destination - delta); + requestAnimationFrame(autoScroll); + } else { + goToSlide(destination / containerWidth); + } + } + } + + function capIndex(idx) { + // ensure given index it inside bounds + return (idx >= slidesCount) ? slidesCount: (idx <= 0) ? 0 : idx; + } + + function updateBufferIndex() { + // update and cap te buffer index + var bufferIndex = 0; + var bufferEdgeSize = (scope.carouselBufferSize - 1) / 2; + if (isBuffered) { + if (scope.carouselIndex <= bufferEdgeSize) { + bufferIndex = 0; + } else if (scope.carouselIndex > slidesCount - scope.carouselBufferSize) { + bufferIndex = slidesCount - scope.carouselBufferSize; + } else { + bufferIndex = scope.carouselIndex - bufferEdgeSize; + } + } + scope.carouselBufferIndex = bufferIndex; + } + + function goToSlide(i, animate) { + if (isNaN(i)) { + i = scope.carouselIndex; + } + if (animate) { + // simulate a swipe so we have the standard animation + // used when external binding index is updated or touch canceed + offset = (i * containerWidth); + swipeEnd(null, null, true); + return; + } + scope.carouselIndex = capIndex(i); + updateBufferIndex(); + // if outside of angular scope, trigger angular digest cycle + // use local digest only for perfs if no index bound + if (scope.$$phase!=='$apply' && scope.$$phase!=='$digest') { + if (isIndexBound) { + scope.$apply(); + } else { + scope.$digest(); + } + } + scroll(); + } + + function getAbsMoveTreshold() { + // return min pixels required to move a slide + return moveTreshold * containerWidth; + } + + function documentMouseUpEvent(event) { + // in case we click outside the carousel, trigger a fake swipeEnd + swipeEnd({ + x: event.clientX, + y: event.clientY + }, event); + } + + function capPosition(x) { + // limit position if start or end of slides + var position = x; + if (scope.carouselIndex===0) { + position = Math.max(-getAbsMoveTreshold(), position); + } else if (scope.carouselIndex===slidesCount-1) { + position = Math.min(((slidesCount-1)*containerWidth + getAbsMoveTreshold()), position); + } + return position; + } + + function swipeStart(coords, event) { + //console.log('swipeStart', coords, event); + $document.bind('mouseup', documentMouseUpEvent); + pressed = true; + startX = coords.x; + + amplitude = 0; + timestamp = Date.now(); + + event.preventDefault(); + event.stopPropagation(); + return false; + } + function swipeMove(coords, event) { + //console.log('swipeMove', coords, event); + var x, delta; + if (pressed) { + x = coords.x; + delta = startX - x; + if (delta > 2 || delta < -2) { + startX = x; + requestAnimationFrame(function() { + scroll(capPosition(offset + delta)); + }); + } + } + event.preventDefault(); + event.stopPropagation(); + return false; + } + + function swipeEnd(coords, event, forceAnimation) { + //console.log('swipeEnd', 'scope.carouselIndex', scope.carouselIndex); + $document.unbind('mouseup', documentMouseUpEvent); + pressed = false; + + destination = offset; + + var minMove = getAbsMoveTreshold(), + currentOffset = (scope.carouselIndex * containerWidth), + absMove = currentOffset - destination, + shouldMove = Math.abs(absMove) > minMove, + moveOffset = shouldMove?(absMove<0)?1:-1:0; + destination = (moveOffset + scope.carouselIndex) * containerWidth; + amplitude = destination - offset; + timestamp = Date.now(); + if (forceAnimation) { + amplitude = offset - currentOffset; + } + requestAnimationFrame(autoScroll); + + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + return false; + } + + $swipe.bind(carousel, { + start: swipeStart, + move: swipeMove, + end: swipeEnd, + cancel: function(event) { + swipeEnd({}, event); + } + }); + + // initialise first slide + goToSlide(scope.carouselIndex); + + // detect supported CSS property + transformProperty = 'transform'; + ['webkit', 'Moz', 'O', 'ms'].every(function (prefix) { + var e = prefix + 'Transform'; + if (typeof document.body.style[e] !== 'undefined') { + transformProperty = e; + return false; + } + return true; + }); + + function onOrientationChange() { + alert('onOrientationChange'); + updateContainerWidth(); + goToSlide(); + } + + // handle orientation change + var winEl = angular.element($window); + winEl.bind('orientationchange', onOrientationChange); + //winEl.bind('resize', onOrientationChange); + + scope.$on('$destroy', function() { + $document.unbind('mouseup', documentMouseUpEvent); + winEl.unbind('orientationchange', onOrientationChange); + // winEl.unbind('resize', onOrientationChange); + }); + + }; + } + }; + }]); -.directive('rnCarousel', ['$compile', '$parse', '$swipe', '$document', '$window', 'CollectionManager', function($compile, $parse, $swipe, $document, $window, CollectionManager) { - /* track number of carousel instances */ - var carousels = 0; +})(); - return { - restrict: 'A', - scope: true, - compile: function(tElement, tAttrs) { - - tElement.addClass('rn-carousel-slides'); - - /* extract the ngRepeat expression from the first li attribute - this expression will be used to update the carousel - buffered carousels will add a slice operator to that expression - - if no ng-repeat found, try to use existing
  • DOM nodes - */ - var liAttributes = tElement.children('li')[0].attributes, - repeatAttribute = liAttributes['ng-repeat'], - isBuffered = false, - originalCollection, - fakeArray; - if (!repeatAttribute) repeatAttribute = liAttributes['data-ng-repeat']; - if (!repeatAttribute) repeatAttribute = liAttributes['x-ng-repeat']; - if (!repeatAttribute) { - var liChilds = tElement.children('li'); - if (liChilds.length < 2) { - throw new Error("carousel: cannot find the ngRepeat attribute OR no childNodes detected"); - } - // if we use DOM nodes instead of ng-repeat, create a fake collection - originalCollection = 'fakeArray'; - fakeArray = Array.prototype.slice.apply(liChilds); - } else { - var exprMatch = repeatAttribute.value.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), - originalItem = exprMatch[1], - trackProperty = exprMatch[3] || ''; - originalCollection = exprMatch[2]; - isBuffered = angular.isDefined(tAttrs['rnCarouselBuffered']); - - /* update the current ngRepeat expression and add a slice operator */ - repeatAttribute.value = originalItem + ' in carouselCollection.cards ' + trackProperty; - } - return function(scope, iElement, iAttrs, controller) { - carousels++; - var carouselId = 'rn-carousel-' + carousels, - swiping = 0, // swipe status - startX = 0, // initial swipe - startOffset = 0, // first move offset - offset = 0, // move offset - minSwipePercentage = 0.1, // minimum swipe required to trigger slide change - containerWidth = 0, // store width of the first slide - skipAnimation = true; - - /* add a wrapper div that will hide the overflow */ - var carousel = iElement.wrap(""), - container = carousel.parent(); - - if (fakeArray) { - // publish the fakeArray on the scope to be able to add indicators - scope.fakeArray = fakeArray; - } - - function getTransformCoordinates(el) { - var results = angular.element(el).css('transform').match(/translate3d\((-?\d+(?:px)?),\s*(-?\d+(?:px)?),\s*(-?\d+(?:px)?)\)/); - if(!results) return [0, 0, 0]; - return results.slice(1, 3); - } - - function transitionEndCallback(event) { - /* when slide transition finished, update buffer */ - if ((event.target && event.target=== carousel[0]) && ( - event.propertyName === 'transform' || - event.propertyName === '-webkit-transform' || - event.propertyName === '-moz-transform') - ) { - scope.$apply(function() { - checkEdges(); - scope.carouselCollection.adjustBuffer(); - updateSlidePosition(true); - }); - - // we should replace the 3d transform with 2d transform to prevent blurry effect on some phones (eg: GS3) - // todo : use non-3d version for browsers not supporting it - carousel.css(translateSlideProperty(getTransformCoordinates(carousel[0]), true)); - - } - } - - function updateSlides(method, items) { - // force apply if no apply/digest phase in progress - function cb() { - skipAnimation = true; - scope.carouselCollection[method](items, true); - } - if(!scope.$$phase) { - scope.$apply(cb); - } else { - cb(); - } - - } - - function addSlides(position, items) { - var method = (position==='after')?'push':'unshift'; - if (items) { - if (angular.isObject(items.promise)) { - items.promise.then(function(items) { - if (items) { - updateSlides(method, items); - } - }); - } else if (angular.isFunction(items.then)) { - items.then(function(items) { - if (items) { - updateSlides(method, items); - } - }); - } else { - updateSlides(method, items); - } - } - } - - function checkEdges() { - var position = scope.carouselCollection.position, - lastIndex = scope.carouselCollection.getLastIndex(), - slides=null; - if (position===0 && angular.isDefined(iAttrs.rnCarouselPrev)) { - slides = $parse(iAttrs.rnCarouselPrev)(scope, { - item: scope.carouselCollection.cards[0] - }); - addSlides('before', slides); - } - if (position===lastIndex && angular.isDefined(iAttrs.rnCarouselNext)) { - slides = $parse(iAttrs.rnCarouselNext)(scope, { - item: scope.carouselCollection.cards[scope.carouselCollection.cards.length - 1] - }); - addSlides('after', slides); - } - } - - var collectionModel = $parse(originalCollection); - var collectionParams = {}; - - /* rn-carousel-index attribute data binding */ - var initialIndex = 0; - if (iAttrs.rnCarouselIndex) { - var indexModel = $parse(iAttrs.rnCarouselIndex); - if (angular.isFunction(indexModel.assign)) { - /* check if this property is assignable then watch it */ - scope.$watch('carouselCollection.index', function(newValue) { - indexModel.assign(scope.$parent, newValue); - }); - initialIndex = indexModel(scope); - scope.$parent.$watch(indexModel, function(newValue, oldValue) { - if (newValue!==undefined) { - scope.carouselCollection.goToIndex(newValue, true); - } - }); - } else if (!isNaN(iAttrs.rnCarouselIndex)) { - /* if user just set an initial number, set it */ - initialIndex = parseInt(iAttrs.rnCarouselIndex, 10); - } - } - - if (angular.isDefined(iAttrs.rnCarouselCycle)) { - collectionParams.cycle = true; - } - collectionParams.index = initialIndex; - - if (isBuffered) { - collectionParams.bufferSize = 3; - collectionParams.buffered = true; - } - - // initialise the collection - scope.carouselCollection = CollectionManager.create(collectionParams); - - scope.$watch('carouselCollection.updated', function(newValue, oldValue) { - if (newValue) updateSlidePosition(); - }); - - var collectionReady = false; - scope.$watch(collectionModel, function(newValue, oldValue) { - // update whole collection contents - // reinitialise index - scope.carouselCollection.setItems(newValue, collectionReady); - collectionReady = true; - if (containerWidth===0) updateContainerWidth(); - updateSlidePosition(); - }); - - if (angular.isDefined(iAttrs.rnCarouselWatch)) { - scope.$watch(originalCollection, function(newValue, oldValue) { - // partial collection update, watch deeply so use carefully - scope.carouselCollection.setItems(newValue, false); - collectionReady = true; - if (containerWidth===0) updateContainerWidth(); - updateSlidePosition(); - }, true); - } - - var vendorPrefixes = ["webkit", "moz"]; - function genCSSProperties(property, value) { - /* cross browser CSS properties generator */ - var css = {}; - css[property] = value; - angular.forEach(vendorPrefixes, function(prefix, idx) { - css['-' + prefix.toLowerCase() + '-' + property] = value; - }); - return css; - } - function translateSlideProperty(offset, is3d) { - if (is3d) { - return genCSSProperties('transform', 'translate3d(' + offset + 'px,0,0)'); - } else { - return genCSSProperties('transform', 'translate(' + offset + 'px,0)'); - } - } - - carousel[0].addEventListener('webkitTransitionEnd', transitionEndCallback, false); // webkit - carousel[0].addEventListener('transitionend', transitionEndCallback, false); // mozilla - - // when orientation change, force width re-redetection - window.addEventListener('orientationchange', resize); - // when window is resized (responsive design) - window.addEventListener('resize', resize); - - function resize () { - updateContainerWidth(); - updateSlidePosition(); - } - - function updateContainerWidth() { - container.css('width', 'auto'); - skipAnimation = true; - var slides = carousel.children('li'); - if (slides.length === 0) { - containerWidth = carousel[0].getBoundingClientRect().width; - } else { - containerWidth = slides[0].getBoundingClientRect().width; - } - container.css('width', containerWidth + 'px'); - return containerWidth; - } - - /* enable carousel indicator */ - if (angular.isDefined(iAttrs.rnCarouselIndicator)) { - var indicator = $compile("")(scope); - container.append(indicator); - } - - function updateSlidePosition(forceSkipAnimation) { - /* trigger carousel position update */ - skipAnimation = !!forceSkipAnimation || skipAnimation; - if (containerWidth===0) updateContainerWidth(); - offset = Math.round(scope.carouselCollection.getRelativeIndex() * -containerWidth); - if (skipAnimation===true) { - carousel.removeClass('rn-carousel-animate') - .addClass('rn-carousel-noanimate') - .css(translateSlideProperty(offset, false)); - } else { - carousel.removeClass('rn-carousel-noanimate') - .addClass('rn-carousel-animate') - .css(translateSlideProperty(offset, true)); - } - skipAnimation = false; - } - - /* bind events */ - - function swipeEnd(coords) { - /* when movement ends, go to next slide or stay on the same */ - $document.unbind('mouseup', documentMouseUpEvent); - if (containerWidth===0) updateContainerWidth(); - if (swiping > 1) { - var lastIndex = scope.carouselCollection.getLastIndex(), - position = scope.carouselCollection.position, - slideOffset = (offset < startOffset)?1:-1, - tmpSlideIndex = Math.min(Math.max(0, position + slideOffset), lastIndex); - var delta = coords.x - startX; - if (Math.abs(delta) <= containerWidth * minSwipePercentage) { - /* prevent swipe if not swipped enough */ - tmpSlideIndex = position; - } - var changed = (position !== tmpSlideIndex); - //console.log(offset, startOffset, slideOffset); - /* reset slide position if same slide (watch not triggered) */ - if (!changed) { - scope.$apply(function() { - updateSlidePosition(); - }); - } else { - scope.$apply(function() { - if (angular.isDefined(iAttrs.rnCarouselCycle)) { - // force slide move even if invalid position for cycle carousels - scope.carouselCollection.position = tmpSlideIndex; - updateSlidePosition(); - } - scope.carouselCollection.goTo(tmpSlideIndex, true); - }); - } - } - swiping = 0; - } - function isInsideCarousel(coords) { - // check coords are inside the carousel area - // we always compute the container dimensions in case user have scrolled the page - var containerRect = container[0].getBoundingClientRect(); - - var isInside = (coords.x > containerRect.left && coords.x < (containerRect.left + containerWidth) && - (coords.y > containerRect.top && coords.y < containerRect.top + containerRect.height)); - - // console.log('isInsideCarousel', { - // containerLeft: containerRect.left, - // containerTop: containerRect.top, - // containerHeight: containerRect.height, - // isInside: isInside, - // x: coords.x, - // y: coords.y - // }); - return isInside; - } - function documentMouseUpEvent(event) { - swipeEnd({ - x: event.clientX, - y: event.clientY - }); - } - // move throttling - var lastMove = null, - // todo: requestAnimationFrame instead - moveDelay = ($window.jasmine || $window.navigator.platform=='iPad')?0:50; - - $swipe.bind(carousel, { - /* use angular $swipe service */ - start: function(coords) { - // console.log('$swipe start'); - /* capture initial event position */ - if (swiping === 0) { - swiping = 1; - startX = coords.x; - } - $document.bind('mouseup', documentMouseUpEvent); - }, - move: function (coords) { - // cancel movement if not inside - if (!isInsideCarousel(coords)) { - // console.log('force end'); - swipeEnd(coords); - return; - } - //console.log('$swipe move'); - if (swiping===0) return; - var deltaX = coords.x - startX; - if (swiping === 1 && deltaX !== 0) { - swiping = 2; - startOffset = offset; - } - else if (swiping === 2) { - var now = (new Date()).getTime(); - if (lastMove && (now-lastMove) < moveDelay) return; - lastMove = now; - var lastIndex = scope.carouselCollection.getLastIndex(), - position = scope.carouselCollection.position; - /* ratio is used for the 'rubber band' effect */ - var ratio = 1; - if ((position === 0 && coords.x > startX) || (position === lastIndex && coords.x < startX)) - ratio = 3; - /* follow cursor movement */ - offset = startOffset + deltaX / ratio; - carousel.css(translateSlideProperty(offset, true)) - .removeClass('rn-carousel-animate') - .addClass('rn-carousel-noanimate'); - } - }, - end: function (coords) { - //console.log('$swipe end'); - swipeEnd(coords); - } - }); - // if (containerWidth===0) updateContainerWidth(); - }; - } - }; -}]); +(function() { + "use strict"; -/** -* CollectionManager.js -* - manage a collection of items -* - rearrange items if buffered or cycle -* - the service is just a wrapper around a non-angular collection manager -**/ -angular.module('angular-carousel') + angular.module('angular-carousel') -.service('CollectionManager', [function() { - - function CollectionManager(options) { - var initial = { - bufferSize: 0, - bufferStart: 0, - buffered: false, - cycle: false, - cycleOffset: 0, // offset - index: 0, // index relative to the original collection - position: 0, // position relative to the current elements - items: [], // total collection - cards: [], // bufered DOM collection - updated: null, // triggers DOM change - debug: false + .filter('carouselSlice', function() { + return function(collection, start, size) { + return collection.slice(start, start + size); }; + }); - var i; - if(options) for(i in options) initial[i] = options[i]; - for(i in initial) this[i] = initial[i]; - - angular.extend(this, initial, options); - - this.init(); - - } - - CollectionManager.prototype.log = function() { - if (this.debug) { - console.log.apply(console, arguments); - // console.log('CollectionManager:', this); - } - }; - CollectionManager.prototype.getPositionFromIndex = function(index) { - return (index + this.cycleOffset) % this.length(); - }; - - CollectionManager.prototype.goToIndex = function(index, delayedUpdate) { - // cap index - index = Math.max(0, Math.min(index, this.getLastIndex())); - if (this.updated && index===this.index) { - this.log('skip position change(same)'); - return false; - } - var position = this.getPositionFromIndex(index); - return this.goTo(position, delayedUpdate); - }; - - CollectionManager.prototype.goTo = function(position, delayedUpdate) { - this.log('goto start', position, delayedUpdate); - - if (this.length()===0) { - this.log('empty, skip gotoIndex'); - return; - } - // cap position - position = Math.max(0, Math.min(position, this.getLastIndex())); - var cycled = false; - if (this.cycle) { - if (position===0) { - // unshift - this.log('cycleAtBeginning', position); - this.cycleAtBeginning(); - position = 1; - this.cycleOffset++; - cycled = true; - } else if (position === this.getLastIndex()) { - // push - this.log('cycleAtEnd', position); - this.cycleAtEnd(); - position--; - this.cycleOffset--; - cycled = true; - } - this.cycleOffset %= this.length(); - } - - this.position = Math.max(0, Math.min(position, this.getLastIndex())); - - var realIndex = (this.position - this.cycleOffset + this.length()) % this.length(); - this.index = Math.max(0, Math.min(realIndex, this.getLastIndex())); - - if (!delayedUpdate) { - this.adjustBuffer(); - } - if (!cycled) this.updated = new Date(); - - }; - - CollectionManager.prototype.next = function() { - // go to next item - if (this.cycle) { - this.goTo((this.position + 1) % this.length()); - } else { - this.goTo(Math.min(this.position + 1, this.getLastIndex())); - } - }; - CollectionManager.prototype.prev = function() { - // go to prev item - if (this.cycle) { - this.goTo((this.position - 1 + this.length()) % this.length()); - } else { - var prevIndex = (this.length()>0)?(Math.max(0, (this.position - 1) % this.length())):0; - this.goTo(prevIndex); - } - }; - CollectionManager.prototype.setBufferSize = function(length) { - this.log('setBufferSize', length); - this.bufferSize = length; - this.adjustBuffer(); - }; - CollectionManager.prototype.isBuffered = function() { - return this.buffered; - }; - CollectionManager.prototype.getRelativeIndex = function() { - var relativeIndex = Math.max(0, Math.min(this.getLastIndex(), this.position - this.bufferStart)); - return relativeIndex; - }; - CollectionManager.prototype.adjustBuffer = function() { - // adjust buffer start position - var maxBufferStart = (this.getLastIndex() + 1 - this.bufferSize) % this.length(); - this.log('maxBufferStart', maxBufferStart); - this.bufferStart = Math.max(0, Math.min(maxBufferStart, this.position - 1)); - this.cards = this.items.slice(this.bufferStart, this.bufferStart + this.bufferSize); - this.log('adjustBuffer from', this.bufferStart, 'to', this.bufferStart + this.bufferSize); - }; - CollectionManager.prototype.length = function() { - return this.items.length; - }; - CollectionManager.prototype.getLastIndex = function() { - var lastIndex = Math.max(0, this.length() - 1); - return lastIndex; - }; - CollectionManager.prototype.init = function() { - //this.log('init', this); - this.setBufferSize(this.isBuffered()?this.bufferSize:this.length()); - if (this.length() > 0) this.goToIndex(this.index); - }; - CollectionManager.prototype.setItems = function(items, reset) { - this.log('setItems', items, reset); - if (reset) { - this.index=0; - this.position=0; - } - this.items = items || []; // prevent internal errors when items is undefined - this.init(); - }; - CollectionManager.prototype.cycleAtEnd = function() { - // extract first item and put it at end - this.push(this.items.shift()); - }; - CollectionManager.prototype.push = function(slide, updateIndex) { - // insert item(s) at end - this.log('push item(s)', slide, updateIndex); - // if (this.items.indexOf(slide)>-1) { - // this.log('item already present, skip it'); - // return; - // } - this.items.push(slide); - if (updateIndex) { - // no need to change index when appending items - this.adjustBuffer(); - this.updated = new Date(); - } - if (!this.buffered) { - this.bufferSize++; - } - }; - CollectionManager.prototype.unshift = function(slide, updateIndex) { - // insert item(s) at beginning - this.log('unshift item(s)', slide, updateIndex); - // if (this.items.indexOf(slide)>-1) { - // this.log('item already present, skip it'); - // return; - // } - this.items.unshift(slide); - if (!this.buffered) { - this.bufferSize++; - } - if (updateIndex) { - this.position++; - this.adjustBuffer(); - this.updated = new Date(); - } - }; - CollectionManager.prototype.cycleAtBeginning = function() { - // extract last item and put it at beginning - this.unshift(this.items.pop()); - }; - return { - create: function(options) { - return new CollectionManager(options); - } - }; -}]); +})(); diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index d689dcf..caa0047 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden}ul.rn-carousel-slides{position:relative;white-space:nowrap;overflow:visible;-webkit-transform:translate(0,0);-moz-transform:translate(0,0);transform:translate(0,0);padding:0;margin:0}ul.rn-carousel-slides>li{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-animate{-webkit-transition:-webkit-transform .1s ease-out;-moz-transition:-moz-transform .1s ease-out;transition:transform .1s ease-out}.rn-carousel-noanimate{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.rn-carousel-indicator{width:100%;text-align:center;position:relative;bottom:20px;height:20px;background-color:#000;background-color:rgba(0,0,0,.6)}.rn-carousel-indicator span{padding:0 5px;color:#333;transition:color .2s ease-out}.rn-carousel-indicator span.active{color:#fff} \ No newline at end of file +.rn-carousel-container{overflow:hidden}.rn-carousel-slides{position:relative;white-space:nowrap;overflow:visible;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index a472486..13a4027 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.0.9 - 2013-10-11 + * @version v0.0.9 - 2014-01-05 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngMobile"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),angular.module("angular-carousel").directive("rnCarouselInfinite",["$parse","$compile",function(t){return{restrict:"EA",transclude:!0,replace:!0,scope:!0,template:"
    ",compile:function(e,n){var i=n.rnCarouselCurrent+" in items";return e.children("li").attr("ng-repeat",i),function(e,n,i){e.items=[t(i.rnCarouselCurrent)(e)],e.$watchCollection("carouselCollection.position",function(n){t(i.rnCarouselCurrent).assign(e.$parent,e.items[n])})}}}}]),angular.module("angular-carousel").directive("rnCarousel",["$compile","$parse","$swipe","$document","$window","CollectionManager",function(t,e,n,i,r,s){var o=0;return{restrict:"A",scope:!0,compile:function(a,l){a.addClass("rn-carousel-slides");var u,c,f=a.children("li")[0].attributes,h=f["ng-repeat"],d=!1;if(h||(h=f["data-ng-repeat"]),h||(h=f["x-ng-repeat"]),h){var p=h.value.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),g=p[1],m=p[3]||"";u=p[2],d=angular.isDefined(l.rnCarouselBuffered),h.value=g+" in carouselCollection.cards "+m}else{var x=a.children("li");if(2>x.length)throw Error("carousel: cannot find the ngRepeat attribute OR no childNodes detected");u="fakeArray",c=Array.prototype.slice.apply(x)}return function(a,l,f){function h(t){var e=angular.element(t).css("transform").match(/translate3d\((-?\d+(?:px)?),\s*(-?\d+(?:px)?),\s*(-?\d+(?:px)?)\)/);return e?e.slice(1,3):[0,0,0]}function p(t){!t.target||t.target!==j[0]||"transform"!==t.propertyName&&"-webkit-transform"!==t.propertyName&&"-moz-transform"!==t.propertyName||(a.$apply(function(){x(),a.carouselCollection.adjustBuffer(),I(!0)}),j.css(v(h(j[0]),!0)))}function g(t,e){function n(){E=!0,a.carouselCollection[t](e,!0)}a.$$phase?n():a.$apply(n)}function m(t,e){var n="after"===t?"push":"unshift";e&&(angular.isObject(e.promise)?e.promise.then(function(t){t&&g(n,t)}):angular.isFunction(e.then)?e.then(function(t){t&&g(n,t)}):g(n,e))}function x(){var t=a.carouselCollection.position,n=a.carouselCollection.getLastIndex(),i=null;0===t&&angular.isDefined(f.rnCarouselPrev)&&(i=e(f.rnCarouselPrev)(a,{item:a.carouselCollection.cards[0]}),m("before",i)),t===n&&angular.isDefined(f.rnCarouselNext)&&(i=e(f.rnCarouselNext)(a,{item:a.carouselCollection.cards[a.carouselCollection.cards.length-1]}),m("after",i))}function C(t,e){var n={};return n[t]=e,angular.forEach(W,function(i){n["-"+i.toLowerCase()+"-"+t]=e}),n}function v(t,e){return e?C("transform","translate3d("+t+"px,0,0)"):C("transform","translate("+t+"px,0)")}function y(){b(),I()}function b(){k.css("width","auto"),E=!0;var t=j.children("li");return D=0===t.length?j[0].getBoundingClientRect().width:t[0].getBoundingClientRect().width,k.css("width",D+"px"),D}function I(t){E=!!t||E,0===D&&b(),A=Math.round(a.carouselCollection.getRelativeIndex()*-D),E===!0?j.removeClass("rn-carousel-animate").addClass("rn-carousel-noanimate").css(v(A,!1)):j.removeClass("rn-carousel-noanimate").addClass("rn-carousel-animate").css(v(A,!0)),E=!1}function w(t){if(i.unbind("mouseup",M),0===D&&b(),S>1){var e=a.carouselCollection.getLastIndex(),n=a.carouselCollection.position,r=z>A?1:-1,s=Math.min(Math.max(0,n+r),e),o=t.x-L;D*T>=Math.abs(o)&&(s=n);var l=n!==s;l?a.$apply(function(){angular.isDefined(f.rnCarouselCycle)&&(a.carouselCollection.position=s,I()),a.carouselCollection.goTo(s,!0)}):a.$apply(function(){I()})}S=0}function $(t){var e=k[0].getBoundingClientRect(),n=t.x>e.left&&t.xe.top&&t.y
  • "),k=j.parent();c&&(a.fakeArray=c);var N=e(u),O={},R=0;if(f.rnCarouselIndex){var P=e(f.rnCarouselIndex);angular.isFunction(P.assign)?(a.$watch("carouselCollection.index",function(t){P.assign(a.$parent,t)}),R=P(a),a.$parent.$watch(P,function(t){void 0!==t&&a.carouselCollection.goToIndex(t,!0)})):isNaN(f.rnCarouselIndex)||(R=parseInt(f.rnCarouselIndex,10))}angular.isDefined(f.rnCarouselCycle)&&(O.cycle=!0),O.index=R,d&&(O.bufferSize=3,O.buffered=!0),a.carouselCollection=s.create(O),a.$watch("carouselCollection.updated",function(t){t&&I()});var F=!1;a.$watch(N,function(t){a.carouselCollection.setItems(t,F),F=!0,0===D&&b(),I()}),angular.isDefined(f.rnCarouselWatch)&&a.$watch(u,function(t){a.carouselCollection.setItems(t,!1),F=!0,0===D&&b(),I()},!0);var W=["webkit","moz"];if(j[0].addEventListener("webkitTransitionEnd",p,!1),j[0].addEventListener("transitionend",p,!1),window.addEventListener("orientationchange",y),window.addEventListener("resize",y),angular.isDefined(f.rnCarouselIndicator)){var X=t("")(a);k.append(X)}var Y=null,q=r.jasmine||"iPad"==r.navigator.platform?0:50;n.bind(j,{start:function(t){0===S&&(S=1,L=t.x),i.bind("mouseup",M)},move:function(t){if(!$(t))return w(t),void 0;if(0!==S){var e=t.x-L;if(1===S&&0!==e)S=2,z=A;else if(2===S){var n=(new Date).getTime();if(Y&&q>n-Y)return;Y=n;var i=a.carouselCollection.getLastIndex(),r=a.carouselCollection.position,s=1;(0===r&&t.x>L||r===i&&L>t.x)&&(s=3),A=z+e/s,j.css(v(A,!0)).removeClass("rn-carousel-animate").addClass("rn-carousel-noanimate")}}},end:function(t){w(t)}})}}}}]),angular.module("angular-carousel").service("CollectionManager",[function(){function t(t){var e,n={bufferSize:0,bufferStart:0,buffered:!1,cycle:!1,cycleOffset:0,index:0,position:0,items:[],cards:[],updated:null,debug:!1};if(t)for(e in t)n[e]=t[e];for(e in n)this[e]=n[e];angular.extend(this,n,t),this.init()}return t.prototype.log=function(){this.debug&&console.log.apply(console,arguments)},t.prototype.getPositionFromIndex=function(t){return(t+this.cycleOffset)%this.length()},t.prototype.goToIndex=function(t,e){if(t=Math.max(0,Math.min(t,this.getLastIndex())),this.updated&&t===this.index)return this.log("skip position change(same)"),!1;var n=this.getPositionFromIndex(t);return this.goTo(n,e)},t.prototype.goTo=function(t,e){if(this.log("goto start",t,e),0===this.length())return this.log("empty, skip gotoIndex"),void 0;t=Math.max(0,Math.min(t,this.getLastIndex()));var n=!1;this.cycle&&(0===t?(this.log("cycleAtBeginning",t),this.cycleAtBeginning(),t=1,this.cycleOffset++,n=!0):t===this.getLastIndex()&&(this.log("cycleAtEnd",t),this.cycleAtEnd(),t--,this.cycleOffset--,n=!0),this.cycleOffset%=this.length()),this.position=Math.max(0,Math.min(t,this.getLastIndex()));var i=(this.position-this.cycleOffset+this.length())%this.length();this.index=Math.max(0,Math.min(i,this.getLastIndex())),e||this.adjustBuffer(),n||(this.updated=new Date)},t.prototype.next=function(){this.cycle?this.goTo((this.position+1)%this.length()):this.goTo(Math.min(this.position+1,this.getLastIndex()))},t.prototype.prev=function(){if(this.cycle)this.goTo((this.position-1+this.length())%this.length());else{var t=this.length()>0?Math.max(0,(this.position-1)%this.length()):0;this.goTo(t)}},t.prototype.setBufferSize=function(t){this.log("setBufferSize",t),this.bufferSize=t,this.adjustBuffer()},t.prototype.isBuffered=function(){return this.buffered},t.prototype.getRelativeIndex=function(){var t=Math.max(0,Math.min(this.getLastIndex(),this.position-this.bufferStart));return t},t.prototype.adjustBuffer=function(){var t=(this.getLastIndex()+1-this.bufferSize)%this.length();this.log("maxBufferStart",t),this.bufferStart=Math.max(0,Math.min(t,this.position-1)),this.cards=this.items.slice(this.bufferStart,this.bufferStart+this.bufferSize),this.log("adjustBuffer from",this.bufferStart,"to",this.bufferStart+this.bufferSize)},t.prototype.length=function(){return this.items.length},t.prototype.getLastIndex=function(){var t=Math.max(0,this.length()-1);return t},t.prototype.init=function(){this.setBufferSize(this.isBuffered()?this.bufferSize:this.length()),this.length()>0&&this.goToIndex(this.index)},t.prototype.setItems=function(t,e){this.log("setItems",t,e),e&&(this.index=0,this.position=0),this.items=t||[],this.init()},t.prototype.cycleAtEnd=function(){this.push(this.items.shift())},t.prototype.push=function(t,e){this.log("push item(s)",t,e),this.items.push(t),e&&(this.adjustBuffer(),this.updated=new Date),this.buffered||this.bufferSize++},t.prototype.unshift=function(t,e){this.log("unshift item(s)",t,e),this.items.unshift(t),this.buffered||this.bufferSize++,e&&(this.position++,this.adjustBuffer(),this.updated=new Date)},t.prototype.cycleAtBeginning=function(){this.unshift(this.items.pop())},{create:function(e){return new t(e)}}}]); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse",function(a,b,c,d){var e=0,f=75,g=.05,h=3;return{restrict:"A",scope:!0,compile:function(i,j){var k,l,m=i.children()[0].attributes,n=!1,o=!1,p=0,q=!1;if(i.addClass("rn-carousel-slides"),i.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=m[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(k=c[1],l=c[2],k)return angular.isDefined(j.rnCarouselBuffered)&&(o=!0,b.value=k+" in "+l+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),n=!0,!1}return!0}),!n){{i.children()}p=i.children().length}return function(i,j,k){function m(){var a=M.children();return E=0===a.length?M[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function r(){N.css("width",m()+"px")}function s(a){isNaN(a)&&(a=i.carouselIndex*E),L=a;var b=-Math.round(L);b+=i.carouselBufferIndex*E,M[0].style[F]="translate3d("+b+"px, 0, 0)"}function t(){var a,b;I&&(a=Date.now()-K,b=I*Math.exp(-a/f),b>h||-h>b?(s(J-b),requestAnimationFrame(t)):w(J/E))}function u(a){return a>=p?p:0>=a?0:a}function v(){var a=0,b=(i.carouselBufferSize-1)/2;o&&(a=i.carouselIndex<=b?0:i.carouselIndex>p-i.carouselBufferSize?p-i.carouselBufferSize:i.carouselIndex-b),i.carouselBufferIndex=a}function w(a,b){return isNaN(a)&&(a=i.carouselIndex),b?(L=a*E,C(null,null,!0),void 0):(i.carouselIndex=u(a),v(),"$apply"!==i.$$phase&&"$digest"!==i.$$phase&&(q?i.$apply():i.$digest()),s(),void 0)}function x(){return g*E}function y(a){C({x:a.clientX,y:a.clientY},a)}function z(a){var b=a;return 0===i.carouselIndex?b=Math.max(-x(),b):i.carouselIndex===p-1&&(b=Math.min((p-1)*E+x(),b)),b}function A(a,b){return c.bind("mouseup",y),G=!0,H=a.x,I=0,K=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function B(a,b){var c,d;return G&&(c=a.x,d=H-c,(d>2||-2>d)&&(H=c,requestAnimationFrame(function(){s(z(L+d))}))),b.preventDefault(),b.stopPropagation(),!1}function C(a,b,d){c.unbind("mouseup",y),G=!1,J=L;var e=x(),f=i.carouselIndex*E,g=f-J,h=Math.abs(g)>e,j=h?0>g?1:-1:0;return J=(j+i.carouselIndex)*E,I=J-L,K=Date.now(),d&&(I=L-f),requestAnimationFrame(t),b&&(b.preventDefault(),b.stopPropagation()),!1}function D(){alert("onOrientationChange"),r(),w()}e++;var E,F,G,H,I,J,K,L=0,M=j.wrap(""),N=M.parent();if(i.carouselBufferIndex=0,i.carouselBufferSize=5,i.carouselIndex=0,k.rnCarouselIndex){var O=d(k.rnCarouselIndex);angular.isFunction(O.assign)?(i.$watch("carouselIndex",function(a){O.assign(i.$parent,a)}),i.carouselIndex=O(i),i.$parent.$watch(O,function(a){void 0!==a&&w(a,!0)}),q=!0):isNaN(k.rnCarouselIndex)||(i.carouselIndex=parseInt(k.rnCarouselIndex,10))}n?i.$watchCollection(l,function(a){p=a.length,E||r(),w(i.carouselIndex)}):r(),a.bind(M,{start:A,move:B,end:C,cancel:function(a){C({},a)}}),w(i.carouselIndex),F="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(F=b,!1):!0});var P=angular.element(b);P.bind("orientationchange",D),i.$on("$destroy",function(){c.unbind("mouseup",y),P.unbind("orientationchange",D)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return a.slice(b,b+c)}})}(); \ No newline at end of file diff --git a/dist/angular-mobile.js b/dist/angular-mobile.js index a572549..8a05eaa 100644 --- a/dist/angular-mobile.js +++ b/dist/angular-mobile.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.0.9 - 2013-10-11 + * @version v0.0.9 - 2014-01-04 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/index.html b/index.html index a879e7f..9ff04ee 100644 --- a/index.html +++ b/index.html @@ -1,252 +1,187 @@ - + + - - - Fork me on GitHub -

    AngularJS Touch Carousel

    -
    Transform your ng-repeat or DOM nodes in a mobile-friendly carousel just by adding a 'rn-carousel' attribute to your ul/li block, thanks to AngularJS magic :)

    - Carousels are data-bound to your ngRepeat collections, can be DOM buffered (good for performance), can cycle over your fixed collection or receive on-demand slides for infinite carousels :) -

    - Try to swipe these demos with your mouse or your finger : -
    - -

    Simple carousel

    - A very basic carousel with indicators

    -
      -
    • -
      -
    • -
    - -

    Simple carousel without ng-repeat

    - This carousel use the ul/li structure to generate the slides

    -
      -
    • Slide #1
    • -
    • Slide #2
    • -
    • Slide #3
    • -
    • Slide #4
    • -
    • Slide #5
    • -
    - - - - - - -

    - This carousel has two way data-binding, custom controls and is buffered (only 3 slides rendered)

    -
      -
    • -
      -
    • -
    - - - - -

    Our Public GitHub repos

    - This carousel has a more advanced template and DOM buffered.

    -
      -
    • -
      {{ repo.name }}
      - {{ repo.description }}
      -
      - watchers : {{ repo.watchers_count }}
      - forks : {{ repo.forks_count }}
      - open issues : {{ repo.open_issues_count }}
      -
    • -
    - -

    Other examples

    - - -
  • Fullscreen Flickr demo (mobile) : demo using Flickr API and a carousel to display Flickr groups feeds
  • -
  • Infinite carousel 1 : using rn-carousel-prev and rn-carousel-next
  • -
  • Infinite carousel 2 : using rn-carousel-infinite and prev/next callbacks
  • -
  • add/remove slides dynamically : using the rn-carousel-watch attribute
  • - - -


    - - - - + + Fork me on GitHub + +

    AngularJS Touch Carousel

    +
    + Transform your ng-repeat or DOM nodes in a mobile-friendly carousel just by adding a 'rn-carousel' attribute to your HTML; AngularJS directives FTW :)

    + Carousels are data-bound to your ngRepeat collections and can be DOM buffered (good for performance) +

    + Try to swipe these demos with your mouse or finger : +
    + +

    ngRepeat demo (buffered carousel)

    +
      +
    • +
      + {{ slide.label }} / {{ slides.length }} +
      + carouselIndex: {{ carouselIndex }}
      + carouselBufferIndex: {{ carouselBufferIndex }}
      +
      +
    • +
    + +

    template-based demo

    +
      +
    • + This is a standard template +
      slide #1
      +
    • +
    • + Here's sophie :
      + +
    • +
    • + A friend of mine :
      + +
    • +
    • + And to finish : + +
    • +
    + +

    buffered ngRepeat carousel with custom controls

    +
      +
    • +
      + {{ slide.label }} / {{ slides2.length }} +
      + carouselIndex: {{ carouselIndex }}
      + carouselBufferIndex: {{ carouselBufferIndex }}
      +
      +
    • +
    +
    + + {{ slideIndex + 1 }} / {{ slides2.length }} + + +
    + +

    Other demos

    + +

    + + + - - - diff --git a/package.json b/package.json index 67c92f1..3a37108 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,27 @@ ], "dependencies": {}, "devDependencies": { - "karma": "~ 0.8.0", - "grunt": ">= 0.4.0", + "karma": "~0.10.9", + "grunt": "~0.4.2", "grunt-contrib-concat": "*", "grunt-contrib-jshint": "*", "grunt-contrib-uglify": "*", "grunt-contrib-connect": "*", "grunt-contrib-cssmin": "~0.6.0", - "grunt-release": "~0.3.3", - "grunt-contrib-watch": "~0.4.4" + "grunt-contrib-watch": "~0.4.4", + "grunt-contrib-copy": "~0.5.0", + "grunt-autoprefixer": "~0.6.3", + "karma-script-launcher": "~0.1.0", + "karma-chrome-launcher": "~0.1.2", + "karma-firefox-launcher": "~0.1.3", + "karma-html2js-preprocessor": "~0.1.0", + "karma-jasmine": "~0.1.5", + "requirejs": "~2.1.9", + "karma-requirejs": "~0.2.1", + "karma-coffee-preprocessor": "~0.1.2", + "karma-phantomjs-launcher": "~0.1.1", + "grunt-karma": "~0.6.2", + "karma-coverage": "~0.1.4" }, "scripts": { "test": "karma start test/karma.conf.js --single-run --browsers Chrome", diff --git a/src/angular-carousel.js b/src/angular-carousel.js index 8d29815..9a30bc3 100644 --- a/src/angular-carousel.js +++ b/src/angular-carousel.js @@ -1,15 +1,11 @@ /*global angular */ /* -Angular touch carousel with CSS GPU accel and slide buffering/cycling +Angular touch carousel with CSS GPU accel and slide buffering http://github.com/revolunet/angular-carousel -TODO : - - skip initial animation - - add/remove ngRepeat collection - - prev/next cbs - - cycle + no initial index ? (is -1 and has bug) - - cycle + indicator */ -angular.module('angular-carousel', ['ngMobile']); +angular.module('angular-carousel', [ + 'ngTouch' +]); diff --git a/src/css/angular-carousel.css b/src/css/angular-carousel.css index feb6054..724da16 100644 --- a/src/css/angular-carousel.css +++ b/src/css/angular-carousel.css @@ -1,55 +1,23 @@ /* generic styles applied to any carousel -must be ul/li +use autoprefixer to build the final CSS */ .rn-carousel-container { - overflow: hidden; + overflow: hidden; } -ul.rn-carousel-slides { - position: relative; - white-space: nowrap; - overflow: visible; - -webkit-transform: translate(0, 0); - -moz-transform: translate(0, 0); - transform: translate(0, 0); - padding: 0; - margin: 0; +.rn-carousel-slides { + position: relative; + white-space: nowrap; + overflow: visible; + transform: translate3d(0, 0, 0); + padding: 0; + margin: 0; } -ul.rn-carousel-slides > li { - white-space: normal; - vertical-align:top; - display: inline-block; - width: 100%; - height: 100%; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; -} -.rn-carousel-animate { - -webkit-transition: -webkit-transform .1s ease-out; - -moz-transition: -moz-transform .1s ease-out; - transition: transform .1s ease-out; -} -.rn-carousel-noanimate { - -webkit-transition: none; - -moz-transition: none; - -ms-transition: none; - -o-transition: none; - transition: none; -} -.rn-carousel-indicator { - width: 100%; - text-align:center; - position:relative; - bottom: 20px; - height:20px; - background-color: rgb(0, 0, 0); - background-color: rgba(0, 0, 0, 0.6); -} -.rn-carousel-indicator span { - padding: 0 5px; - color: #333; - transition: color .2s ease-out; -} -.rn-carousel-indicator span.active { - color:white; +.rn-carousel-slide { + white-space: normal; + vertical-align:top; + display: inline-block; + width: 100%; + height: 100%; + backface-visibility: hidden; } diff --git a/src/directives/rn-carousel-infinite.js b/src/directives/rn-carousel-infinite.js deleted file mode 100644 index 63b52fe..0000000 --- a/src/directives/rn-carousel-infinite.js +++ /dev/null @@ -1,23 +0,0 @@ -angular.module('angular-carousel') - -.directive('rnCarouselInfinite', ['$parse', '$compile', function($parse, $compile) { - return { - restrict: 'EA', - transclude: true, - replace: true, - scope: true, - template: '
    ', - compile: function(tElement, tAttrs, linker) { - var repeatExpr = tAttrs.rnCarouselCurrent + ' in items'; - tElement.children('li').attr('ng-repeat', repeatExpr); - return function(scope, iElement, iAttrs) { - // wrap the original content in a real rn-carousel - scope.items = [$parse(iAttrs.rnCarouselCurrent)(scope)]; - scope.$watchCollection('carouselCollection.position', function(newValue) { - // assign the new item to the parent scope - $parse(iAttrs.rnCarouselCurrent).assign(scope.$parent, scope.items[newValue]); - }); - }; - } - }; -}]); diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 4e5af94..0a7fd87 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -1,388 +1,342 @@ -angular.module('angular-carousel') - -.directive('rnCarousel', ['$compile', '$parse', '$swipe', '$document', '$window', 'CollectionManager', function($compile, $parse, $swipe, $document, $window, CollectionManager) { - /* track number of carousel instances */ - var carousels = 0; - - return { - restrict: 'A', - scope: true, - compile: function(tElement, tAttrs) { - - tElement.addClass('rn-carousel-slides'); - - /* extract the ngRepeat expression from the first li attribute - this expression will be used to update the carousel - buffered carousels will add a slice operator to that expression - - if no ng-repeat found, try to use existing
  • DOM nodes - */ - var liAttributes = tElement.children('li')[0].attributes, - repeatAttribute = liAttributes['ng-repeat'], - isBuffered = false, - originalCollection, - fakeArray; - if (!repeatAttribute) repeatAttribute = liAttributes['data-ng-repeat']; - if (!repeatAttribute) repeatAttribute = liAttributes['x-ng-repeat']; - if (!repeatAttribute) { - var liChilds = tElement.children('li'); - if (liChilds.length < 2) { - throw new Error("carousel: cannot find the ngRepeat attribute OR no childNodes detected"); - } - // if we use DOM nodes instead of ng-repeat, create a fake collection - originalCollection = 'fakeArray'; - fakeArray = Array.prototype.slice.apply(liChilds); - } else { - var exprMatch = repeatAttribute.value.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), - originalItem = exprMatch[1], - trackProperty = exprMatch[3] || ''; - originalCollection = exprMatch[2]; - isBuffered = angular.isDefined(tAttrs['rnCarouselBuffered']); - - /* update the current ngRepeat expression and add a slice operator */ - repeatAttribute.value = originalItem + ' in carouselCollection.cards ' + trackProperty; - } - return function(scope, iElement, iAttrs, controller) { - carousels++; - var carouselId = 'rn-carousel-' + carousels, - swiping = 0, // swipe status - startX = 0, // initial swipe - startOffset = 0, // first move offset - offset = 0, // move offset - minSwipePercentage = 0.1, // minimum swipe required to trigger slide change - containerWidth = 0, // store width of the first slide - skipAnimation = true; - - /* add a wrapper div that will hide the overflow */ - var carousel = iElement.wrap(""), - container = carousel.parent(); - - if (fakeArray) { - // publish the fakeArray on the scope to be able to add indicators - scope.fakeArray = fakeArray; - } - - function getTransformCoordinates(el) { - var results = angular.element(el).css('transform').match(/translate3d\((-?\d+(?:px)?),\s*(-?\d+(?:px)?),\s*(-?\d+(?:px)?)\)/); - if(!results) return [0, 0, 0]; - return results.slice(1, 3); - } - - function transitionEndCallback(event) { - /* when slide transition finished, update buffer */ - if ((event.target && event.target=== carousel[0]) && ( - event.propertyName === 'transform' || - event.propertyName === '-webkit-transform' || - event.propertyName === '-moz-transform') - ) { - scope.$apply(function() { - checkEdges(); - scope.carouselCollection.adjustBuffer(); - updateSlidePosition(true); - }); - - // we should replace the 3d transform with 2d transform to prevent blurry effect on some phones (eg: GS3) - // todo : use non-3d version for browsers not supporting it - carousel.css(translateSlideProperty(getTransformCoordinates(carousel[0]), true)); - - } - } - - function updateSlides(method, items) { - // force apply if no apply/digest phase in progress - function cb() { - skipAnimation = true; - scope.carouselCollection[method](items, true); - } - if(!scope.$$phase) { - scope.$apply(cb); - } else { - cb(); - } - - } - - function addSlides(position, items) { - var method = (position==='after')?'push':'unshift'; - if (items) { - if (angular.isObject(items.promise)) { - items.promise.then(function(items) { - if (items) { - updateSlides(method, items); - } - }); - } else if (angular.isFunction(items.then)) { - items.then(function(items) { - if (items) { - updateSlides(method, items); - } - }); - } else { - updateSlides(method, items); - } - } - } - - function checkEdges() { - var position = scope.carouselCollection.position, - lastIndex = scope.carouselCollection.getLastIndex(), - slides=null; - if (position===0 && angular.isDefined(iAttrs.rnCarouselPrev)) { - slides = $parse(iAttrs.rnCarouselPrev)(scope, { - item: scope.carouselCollection.cards[0] - }); - addSlides('before', slides); - } - if (position===lastIndex && angular.isDefined(iAttrs.rnCarouselNext)) { - slides = $parse(iAttrs.rnCarouselNext)(scope, { - item: scope.carouselCollection.cards[scope.carouselCollection.cards.length - 1] - }); - addSlides('after', slides); - } - } - - var collectionModel = $parse(originalCollection); - var collectionParams = {}; - - /* rn-carousel-index attribute data binding */ - var initialIndex = 0; - if (iAttrs.rnCarouselIndex) { - var indexModel = $parse(iAttrs.rnCarouselIndex); - if (angular.isFunction(indexModel.assign)) { - /* check if this property is assignable then watch it */ - scope.$watch('carouselCollection.index', function(newValue) { - indexModel.assign(scope.$parent, newValue); - }); - initialIndex = indexModel(scope); - scope.$parent.$watch(indexModel, function(newValue, oldValue) { - if (newValue!==undefined) { - scope.carouselCollection.goToIndex(newValue, true); - } - }); - } else if (!isNaN(iAttrs.rnCarouselIndex)) { - /* if user just set an initial number, set it */ - initialIndex = parseInt(iAttrs.rnCarouselIndex, 10); - } - } - - if (angular.isDefined(iAttrs.rnCarouselCycle)) { - collectionParams.cycle = true; - } - collectionParams.index = initialIndex; - - if (isBuffered) { - collectionParams.bufferSize = 3; - collectionParams.buffered = true; - } - - // initialise the collection - scope.carouselCollection = CollectionManager.create(collectionParams); - - scope.$watch('carouselCollection.updated', function(newValue, oldValue) { - if (newValue) updateSlidePosition(); - }); - - var collectionReady = false; - scope.$watch(collectionModel, function(newValue, oldValue) { - // update whole collection contents - // reinitialise index - scope.carouselCollection.setItems(newValue, collectionReady); - collectionReady = true; - if (containerWidth===0) updateContainerWidth(); - updateSlidePosition(); - }); - - if (angular.isDefined(iAttrs.rnCarouselWatch)) { - scope.$watch(originalCollection, function(newValue, oldValue) { - // partial collection update, watch deeply so use carefully - scope.carouselCollection.setItems(newValue, false); - collectionReady = true; - if (containerWidth===0) updateContainerWidth(); - updateSlidePosition(); - }, true); - } - - var vendorPrefixes = ["webkit", "moz"]; - function genCSSProperties(property, value) { - /* cross browser CSS properties generator */ - var css = {}; - css[property] = value; - angular.forEach(vendorPrefixes, function(prefix, idx) { - css['-' + prefix.toLowerCase() + '-' + property] = value; - }); - return css; - } - function translateSlideProperty(offset, is3d) { - if (is3d) { - return genCSSProperties('transform', 'translate3d(' + offset + 'px,0,0)'); - } else { - return genCSSProperties('transform', 'translate(' + offset + 'px,0)'); - } - } - - carousel[0].addEventListener('webkitTransitionEnd', transitionEndCallback, false); // webkit - carousel[0].addEventListener('transitionend', transitionEndCallback, false); // mozilla - - // when orientation change, force width re-redetection - window.addEventListener('orientationchange', resize); - // when window is resized (responsive design) - window.addEventListener('resize', resize); - - function resize () { - updateContainerWidth(); - updateSlidePosition(); - } - - function updateContainerWidth() { - container.css('width', 'auto'); - skipAnimation = true; - var slides = carousel.children('li'); - if (slides.length === 0) { - containerWidth = carousel[0].getBoundingClientRect().width; - } else { - containerWidth = slides[0].getBoundingClientRect().width; - } - container.css('width', containerWidth + 'px'); - return containerWidth; - } - - /* enable carousel indicator */ - if (angular.isDefined(iAttrs.rnCarouselIndicator)) { - var indicator = $compile("")(scope); - container.append(indicator); - } - - function updateSlidePosition(forceSkipAnimation) { - /* trigger carousel position update */ - skipAnimation = !!forceSkipAnimation || skipAnimation; - if (containerWidth===0) updateContainerWidth(); - offset = Math.round(scope.carouselCollection.getRelativeIndex() * -containerWidth); - if (skipAnimation===true) { - carousel.removeClass('rn-carousel-animate') - .addClass('rn-carousel-noanimate') - .css(translateSlideProperty(offset, false)); - } else { - carousel.removeClass('rn-carousel-noanimate') - .addClass('rn-carousel-animate') - .css(translateSlideProperty(offset, true)); - } - skipAnimation = false; - } - - /* bind events */ - - function swipeEnd(coords) { - /* when movement ends, go to next slide or stay on the same */ - $document.unbind('mouseup', documentMouseUpEvent); - if (containerWidth===0) updateContainerWidth(); - if (swiping > 1) { - var lastIndex = scope.carouselCollection.getLastIndex(), - position = scope.carouselCollection.position, - slideOffset = (offset < startOffset)?1:-1, - tmpSlideIndex = Math.min(Math.max(0, position + slideOffset), lastIndex); - var delta = coords.x - startX; - if (Math.abs(delta) <= containerWidth * minSwipePercentage) { - /* prevent swipe if not swipped enough */ - tmpSlideIndex = position; - } - var changed = (position !== tmpSlideIndex); - //console.log(offset, startOffset, slideOffset); - /* reset slide position if same slide (watch not triggered) */ - if (!changed) { - scope.$apply(function() { - updateSlidePosition(); - }); - } else { - scope.$apply(function() { - if (angular.isDefined(iAttrs.rnCarouselCycle)) { - // force slide move even if invalid position for cycle carousels - scope.carouselCollection.position = tmpSlideIndex; - updateSlidePosition(); - } - scope.carouselCollection.goTo(tmpSlideIndex, true); +(function() { + "use strict"; + + angular.module('angular-carousel') + + .directive('rnCarousel', ['$swipe', '$window', '$document', '$parse', function($swipe, $window, $document, $parse) { + // internal ids to allow multiple instances + var carouselId = 0, + // used to compute the sliding speed + timeConstant = 75, + // in container % how much we need to drag to trigger the slide change + moveTreshold = 0.05, + // in absolute pixels, at which distance the slide stick to the edge on release + rubberTreshold = 3; + + return { + restrict: 'A', + scope: true, + compile: function(tElement, tAttributes) { + // use the compile phase to customize the DOM + var firstChildAttributes = tElement.children()[0].attributes, + isRepeatBased = false, + isBuffered = false, + slidesCount = 0, + isIndexBound = false, + repeatItem, + repeatCollection; + + // add CSS classes + tElement.addClass('rn-carousel-slides'); + tElement.children().addClass('rn-carousel-slide'); + + // try to find an ngRepeat expression + // at this point, the attributes are not yet normalized so we need to try various syntax + ['ng-repeat', 'data-ng-repeat', 'x-ng-repeat'].every(function(attr) { + var repeatAttribute = firstChildAttributes[attr]; + if (angular.isDefined(repeatAttribute)) { + // ngRepeat regexp extracted from angular 1.2.7 src + var exprMatch = repeatAttribute.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/), + trackProperty = exprMatch[3]; + + repeatItem = exprMatch[1]; + repeatCollection = exprMatch[2]; + + if (repeatItem) { + if (angular.isDefined(tAttributes['rnCarouselBuffered'])) { + // update the current ngRepeat expression and add a slice operator if buffered + isBuffered = true; + repeatAttribute.value = repeatItem + ' in ' + repeatCollection + '|carouselSlice:carouselBufferIndex:carouselBufferSize'; + if (trackProperty) { + repeatAttribute.value += ' track by ' + trackProperty; + } + } + isRepeatBased = true; + return false; + } + } + return true; }); - } - } - swiping = 0; - } - function isInsideCarousel(coords) { - // check coords are inside the carousel area - // we always compute the container dimensions in case user have scrolled the page - var containerRect = container[0].getBoundingClientRect(); - - var isInside = (coords.x > containerRect.left && coords.x < (containerRect.left + containerWidth) && - (coords.y > containerRect.top && coords.y < containerRect.top + containerRect.height)); - - // console.log('isInsideCarousel', { - // containerLeft: containerRect.left, - // containerTop: containerRect.top, - // containerHeight: containerRect.height, - // isInside: isInside, - // x: coords.x, - // y: coords.y - // }); - return isInside; - } - function documentMouseUpEvent(event) { - swipeEnd({ - x: event.clientX, - y: event.clientY - }); - } - // move throttling - var lastMove = null, - // todo: requestAnimationFrame instead - moveDelay = ($window.jasmine || $window.navigator.platform=='iPad')?0:50; - - $swipe.bind(carousel, { - /* use angular $swipe service */ - start: function(coords) { - // console.log('$swipe start'); - /* capture initial event position */ - if (swiping === 0) { - swiping = 1; - startX = coords.x; - } - $document.bind('mouseup', documentMouseUpEvent); - }, - move: function (coords) { - // cancel movement if not inside - if (!isInsideCarousel(coords)) { - // console.log('force end'); - swipeEnd(coords); - return; - } - //console.log('$swipe move'); - if (swiping===0) return; - var deltaX = coords.x - startX; - if (swiping === 1 && deltaX !== 0) { - swiping = 2; - startOffset = offset; - } - else if (swiping === 2) { - var now = (new Date()).getTime(); - if (lastMove && (now-lastMove) < moveDelay) return; - lastMove = now; - var lastIndex = scope.carouselCollection.getLastIndex(), - position = scope.carouselCollection.position; - /* ratio is used for the 'rubber band' effect */ - var ratio = 1; - if ((position === 0 && coords.x > startX) || (position === lastIndex && coords.x < startX)) - ratio = 3; - /* follow cursor movement */ - offset = startOffset + deltaX / ratio; - carousel.css(translateSlideProperty(offset, true)) - .removeClass('rn-carousel-animate') - .addClass('rn-carousel-noanimate'); + if (!isRepeatBased) { + // basic template based carousel + var liChilds = tElement.children(); + slidesCount = tElement.children().length; + } + + return function(scope, iElement, iAttributes) { + + carouselId++; + + var containerWidth, + transformProperty, + pressed, + startX, + amplitude, + offset = 0, + destination, + // javascript based animation easing + timestamp; + + // add a wrapper div that will hide the overflow + var carousel = iElement.wrap(""), + container = carousel.parent(); + + scope.carouselBufferIndex = 0; + scope.carouselBufferSize = 5; + scope.carouselIndex = 0; + + // handle index databinding + if (iAttributes.rnCarouselIndex) { + var indexModel = $parse(iAttributes.rnCarouselIndex); + if (angular.isFunction(indexModel.assign)) { + /* check if this property is assignable then watch it */ + scope.$watch('carouselIndex', function(newValue) { + indexModel.assign(scope.$parent, newValue); + }); + scope.carouselIndex = indexModel(scope); + scope.$parent.$watch(indexModel, function(newValue, oldValue) { + if (newValue!==undefined) { + // todo: ensure valid + goToSlide(newValue, true); + } + }); + isIndexBound = true; + } else if (!isNaN(iAttributes.rnCarouselIndex)) { + /* if user just set an initial number, set it */ + scope.carouselIndex = parseInt(iAttributes.rnCarouselIndex, 10); + } + } + + // watch the given collection + if (isRepeatBased) { + scope.$watchCollection(repeatCollection, function(newValue, oldValue) { + //console.log('collection updated', repeatCollection, arguments); + slidesCount = newValue.length; + if (!containerWidth) updateContainerWidth(); + goToSlide(scope.carouselIndex); + }); + } else { + updateContainerWidth(); + } + + function getCarouselWidth() { + // container.css('width', 'auto'); + var slides = carousel.children(); + if (slides.length === 0) { + containerWidth = carousel[0].getBoundingClientRect().width; + } else { + containerWidth = slides[0].getBoundingClientRect().width; + } + //console.log('getCarouselWidth', containerWidth); + return containerWidth; + } + + function updateContainerWidth() { + // force the carousel container width to match the first slide width + container.css('width', getCarouselWidth() + 'px'); + } + + function scroll(x) { + // use CSS 3D transform to move the carousel + //console.log('scroll', x, 'index', scope.carouselIndex); + if (isNaN(x)) { + x = scope.carouselIndex * containerWidth; + } + + offset = x; + var move = -Math.round(offset); + move += (scope.carouselBufferIndex * containerWidth); + carousel[0].style[transformProperty] = 'translate3d(' + move + 'px, 0, 0)'; + } + + function autoScroll() { + // scroll smoothly to "destination" until we reach it + // using requestAnimationFrame + var elapsed, delta; + + if (amplitude) { + elapsed = Date.now() - timestamp; + delta = amplitude * Math.exp(-elapsed / timeConstant); + if (delta > rubberTreshold || delta < -rubberTreshold) { + scroll(destination - delta); + requestAnimationFrame(autoScroll); + } else { + goToSlide(destination / containerWidth); + } + } + } + + function capIndex(idx) { + // ensure given index it inside bounds + return (idx >= slidesCount) ? slidesCount: (idx <= 0) ? 0 : idx; + } + + function updateBufferIndex() { + // update and cap te buffer index + var bufferIndex = 0; + var bufferEdgeSize = (scope.carouselBufferSize - 1) / 2; + if (isBuffered) { + if (scope.carouselIndex <= bufferEdgeSize) { + bufferIndex = 0; + } else if (scope.carouselIndex > slidesCount - scope.carouselBufferSize) { + bufferIndex = slidesCount - scope.carouselBufferSize; + } else { + bufferIndex = scope.carouselIndex - bufferEdgeSize; + } + } + scope.carouselBufferIndex = bufferIndex; + } + + function goToSlide(i, animate) { + if (isNaN(i)) { + i = scope.carouselIndex; + } + if (animate) { + // simulate a swipe so we have the standard animation + // used when external binding index is updated or touch canceed + offset = (i * containerWidth); + swipeEnd(null, null, true); + return; + } + scope.carouselIndex = capIndex(i); + updateBufferIndex(); + // if outside of angular scope, trigger angular digest cycle + // use local digest only for perfs if no index bound + if (scope.$$phase!=='$apply' && scope.$$phase!=='$digest') { + if (isIndexBound) { + scope.$apply(); + } else { + scope.$digest(); + } + } + scroll(); + } + + function getAbsMoveTreshold() { + // return min pixels required to move a slide + return moveTreshold * containerWidth; + } + + function documentMouseUpEvent(event) { + // in case we click outside the carousel, trigger a fake swipeEnd + swipeEnd({ + x: event.clientX, + y: event.clientY + }, event); + } + + function capPosition(x) { + // limit position if start or end of slides + var position = x; + if (scope.carouselIndex===0) { + position = Math.max(-getAbsMoveTreshold(), position); + } else if (scope.carouselIndex===slidesCount-1) { + position = Math.min(((slidesCount-1)*containerWidth + getAbsMoveTreshold()), position); + } + return position; + } + + function swipeStart(coords, event) { + //console.log('swipeStart', coords, event); + $document.bind('mouseup', documentMouseUpEvent); + pressed = true; + startX = coords.x; + + amplitude = 0; + timestamp = Date.now(); + + event.preventDefault(); + event.stopPropagation(); + return false; + } + function swipeMove(coords, event) { + //console.log('swipeMove', coords, event); + var x, delta; + if (pressed) { + x = coords.x; + delta = startX - x; + if (delta > 2 || delta < -2) { + startX = x; + requestAnimationFrame(function() { + scroll(capPosition(offset + delta)); + }); + } + } + event.preventDefault(); + event.stopPropagation(); + return false; + } + + function swipeEnd(coords, event, forceAnimation) { + //console.log('swipeEnd', 'scope.carouselIndex', scope.carouselIndex); + $document.unbind('mouseup', documentMouseUpEvent); + pressed = false; + + destination = offset; + + var minMove = getAbsMoveTreshold(), + currentOffset = (scope.carouselIndex * containerWidth), + absMove = currentOffset - destination, + shouldMove = Math.abs(absMove) > minMove, + moveOffset = shouldMove?(absMove<0)?1:-1:0; + destination = (moveOffset + scope.carouselIndex) * containerWidth; + amplitude = destination - offset; + timestamp = Date.now(); + if (forceAnimation) { + amplitude = offset - currentOffset; + } + requestAnimationFrame(autoScroll); + + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + return false; + } + + $swipe.bind(carousel, { + start: swipeStart, + move: swipeMove, + end: swipeEnd, + cancel: function(event) { + swipeEnd({}, event); + } + }); + + // initialise first slide + goToSlide(scope.carouselIndex); + + // detect supported CSS property + transformProperty = 'transform'; + ['webkit', 'Moz', 'O', 'ms'].every(function (prefix) { + var e = prefix + 'Transform'; + if (typeof document.body.style[e] !== 'undefined') { + transformProperty = e; + return false; + } + return true; + }); + + function onOrientationChange() { + alert('onOrientationChange'); + updateContainerWidth(); + goToSlide(); + } + + // handle orientation change + var winEl = angular.element($window); + winEl.bind('orientationchange', onOrientationChange); + //winEl.bind('resize', onOrientationChange); + + scope.$on('$destroy', function() { + $document.unbind('mouseup', documentMouseUpEvent); + winEl.unbind('orientationchange', onOrientationChange); + // winEl.unbind('resize', onOrientationChange); + }); + + }; } - }, - end: function (coords) { - //console.log('$swipe end'); - swipeEnd(coords); - } - }); - // if (containerWidth===0) updateContainerWidth(); - }; - } - }; -}]); + }; + }]); + +})(); diff --git a/src/directives/sliceFilter.js b/src/directives/sliceFilter.js new file mode 100644 index 0000000..e456f2f --- /dev/null +++ b/src/directives/sliceFilter.js @@ -0,0 +1,12 @@ +(function() { + "use strict"; + + angular.module('angular-carousel') + + .filter('carouselSlice', function() { + return function(collection, start, size) { + return collection.slice(start, start + size); + }; + }); + +})(); diff --git a/src/services/CollectionManager.js b/src/services/CollectionManager.js deleted file mode 100644 index b38ab11..0000000 --- a/src/services/CollectionManager.js +++ /dev/null @@ -1,203 +0,0 @@ -/** -* CollectionManager.js -* - manage a collection of items -* - rearrange items if buffered or cycle -* - the service is just a wrapper around a non-angular collection manager -**/ -angular.module('angular-carousel') - -.service('CollectionManager', [function() { - - function CollectionManager(options) { - var initial = { - bufferSize: 0, - bufferStart: 0, - buffered: false, - cycle: false, - cycleOffset: 0, // offset - index: 0, // index relative to the original collection - position: 0, // position relative to the current elements - items: [], // total collection - cards: [], // bufered DOM collection - updated: null, // triggers DOM change - debug: false - }; - - var i; - if(options) for(i in options) initial[i] = options[i]; - for(i in initial) this[i] = initial[i]; - - angular.extend(this, initial, options); - - this.init(); - - } - - CollectionManager.prototype.log = function() { - if (this.debug) { - console.log.apply(console, arguments); - // console.log('CollectionManager:', this); - } - }; - CollectionManager.prototype.getPositionFromIndex = function(index) { - return (index + this.cycleOffset) % this.length(); - }; - - CollectionManager.prototype.goToIndex = function(index, delayedUpdate) { - // cap index - index = Math.max(0, Math.min(index, this.getLastIndex())); - if (this.updated && index===this.index) { - this.log('skip position change(same)'); - return false; - } - var position = this.getPositionFromIndex(index); - return this.goTo(position, delayedUpdate); - }; - - CollectionManager.prototype.goTo = function(position, delayedUpdate) { - this.log('goto start', position, delayedUpdate); - - if (this.length()===0) { - this.log('empty, skip gotoIndex'); - return; - } - // cap position - position = Math.max(0, Math.min(position, this.getLastIndex())); - var cycled = false; - if (this.cycle) { - if (position===0) { - // unshift - this.log('cycleAtBeginning', position); - this.cycleAtBeginning(); - position = 1; - this.cycleOffset++; - cycled = true; - } else if (position === this.getLastIndex()) { - // push - this.log('cycleAtEnd', position); - this.cycleAtEnd(); - position--; - this.cycleOffset--; - cycled = true; - } - this.cycleOffset %= this.length(); - } - - this.position = Math.max(0, Math.min(position, this.getLastIndex())); - - var realIndex = (this.position - this.cycleOffset + this.length()) % this.length(); - this.index = Math.max(0, Math.min(realIndex, this.getLastIndex())); - - if (!delayedUpdate) { - this.adjustBuffer(); - } - if (!cycled) this.updated = new Date(); - - }; - - CollectionManager.prototype.next = function() { - // go to next item - if (this.cycle) { - this.goTo((this.position + 1) % this.length()); - } else { - this.goTo(Math.min(this.position + 1, this.getLastIndex())); - } - }; - CollectionManager.prototype.prev = function() { - // go to prev item - if (this.cycle) { - this.goTo((this.position - 1 + this.length()) % this.length()); - } else { - var prevIndex = (this.length()>0)?(Math.max(0, (this.position - 1) % this.length())):0; - this.goTo(prevIndex); - } - }; - CollectionManager.prototype.setBufferSize = function(length) { - this.log('setBufferSize', length); - this.bufferSize = length; - this.adjustBuffer(); - }; - CollectionManager.prototype.isBuffered = function() { - return this.buffered; - }; - CollectionManager.prototype.getRelativeIndex = function() { - var relativeIndex = Math.max(0, Math.min(this.getLastIndex(), this.position - this.bufferStart)); - return relativeIndex; - }; - CollectionManager.prototype.adjustBuffer = function() { - // adjust buffer start position - var maxBufferStart = (this.getLastIndex() + 1 - this.bufferSize) % this.length(); - this.log('maxBufferStart', maxBufferStart); - this.bufferStart = Math.max(0, Math.min(maxBufferStart, this.position - 1)); - this.cards = this.items.slice(this.bufferStart, this.bufferStart + this.bufferSize); - this.log('adjustBuffer from', this.bufferStart, 'to', this.bufferStart + this.bufferSize); - }; - CollectionManager.prototype.length = function() { - return this.items.length; - }; - CollectionManager.prototype.getLastIndex = function() { - var lastIndex = Math.max(0, this.length() - 1); - return lastIndex; - }; - CollectionManager.prototype.init = function() { - //this.log('init', this); - this.setBufferSize(this.isBuffered()?this.bufferSize:this.length()); - if (this.length() > 0) this.goToIndex(this.index); - }; - CollectionManager.prototype.setItems = function(items, reset) { - this.log('setItems', items, reset); - if (reset) { - this.index=0; - this.position=0; - } - this.items = items || []; // prevent internal errors when items is undefined - this.init(); - }; - CollectionManager.prototype.cycleAtEnd = function() { - // extract first item and put it at end - this.push(this.items.shift()); - }; - CollectionManager.prototype.push = function(slide, updateIndex) { - // insert item(s) at end - this.log('push item(s)', slide, updateIndex); - // if (this.items.indexOf(slide)>-1) { - // this.log('item already present, skip it'); - // return; - // } - this.items.push(slide); - if (updateIndex) { - // no need to change index when appending items - this.adjustBuffer(); - this.updated = new Date(); - } - if (!this.buffered) { - this.bufferSize++; - } - }; - CollectionManager.prototype.unshift = function(slide, updateIndex) { - // insert item(s) at beginning - this.log('unshift item(s)', slide, updateIndex); - // if (this.items.indexOf(slide)>-1) { - // this.log('item already present, skip it'); - // return; - // } - this.items.unshift(slide); - if (!this.buffered) { - this.bufferSize++; - } - if (updateIndex) { - this.position++; - this.adjustBuffer(); - this.updated = new Date(); - } - }; - CollectionManager.prototype.cycleAtBeginning = function() { - // extract last item and put it at beginning - this.unshift(this.items.pop()); - }; - return { - create: function(options) { - return new CollectionManager(options); - } - }; -}]); diff --git a/test.html b/test.html deleted file mode 100644 index d4567a3..0000000 --- a/test.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - -

    test page - - - - - -

    - -
      -
    • -

      -

      carouselCollection.index: {{ carouselCollection.index }}

      -

      carouselCollection.position: {{ carouselCollection.position }}

      -
      
      -      
    • -
    - - - - - - - - - - - - diff --git a/test/karma.conf.js b/test/karma.conf.js index 6249df7..5e9ebe4 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -1,76 +1,70 @@ -// Testacular configuration file -// -// For all available config options and default values, see: -// https://github.com/vojtajina/testacular/blob/stable/lib/config.js#L54 +var grunt = require('grunt'); +module.exports = function ( karma ) { + karma.set({ + /** + * From where to look for files, starting with the location of this file. + */ + basePath: './..', -// base path, that will be used to resolve files and exclude -basePath = './..'; + /** + * This is the list of file patterns to load into the browser during testing. + */ + files: [ + 'bower_components/angular/angular.js', + 'bower_components/angular-touch/angular-touch.js', + 'bower_components/angular-mocks/angular-mocks.js', + 'dist/angular-carousel.js', + 'test/unit/*.js' + ], -// frameworks to use -// frameworks = ['jasmine']; + frameworks: [ 'jasmine' ], + plugins: [ 'karma-jasmine', 'karma-firefox-launcher', 'karma-chrome-launcher', 'karma-coverage'], -// list of files / patterns to load in the browser -files = [ - JASMINE, - JASMINE_ADAPTER, - 'components/jquery/jquery.min.js', - 'components/angular/angular.js', - 'dist/angular-mobile.js', - 'lib/browserTrigger.js', - 'components/angular/angular-mocks.js', - 'dist/angular-carousel.js', - 'test/unit/*.js' -]; + logLevel: 'DEBUG', + /** + * How to report, by default. + */ + reporters: ['dots', 'coverage'], -// list of files to exclude -exclude = []; + preprocessors: { + // source files, that you wanna generate coverage for + // do not include tests or libraries + // (these files will be instrumented by Istanbul) + '../dist/*.js': ['coverage'] + }, -// use dots reporter, as travis terminal does not support escaping sequences -// possible values: 'dots', 'progress', 'junit' -// CLI --reporters progress -// 'coverage', -reporters = ['progress']; + coverageReporter: { + type : 'html', + dir : 'coverage/' + }, -// web server port -// CLI --port 9876 -port = 9876; + /** + * On which port should the browser connect, on which port is the test runner + * operating, and what is the URL path for the browser to use. + */ + port: 7018, + runnerPort: 7100, + urlRoot: '/', -// cli runner port -// CLI --runner-port 9100 -runnerPort = 9100; + /** + * Disable file watching by default. + */ + autoWatch: false, -// enable / disable colors in the output (reporters and logs) -// CLI --colors --no-colors -colors = true; - -// level of logging -// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG -// CLI --log-level debug -logLevel = LOG_INFO; - -// enable / disable watching file and executing tests whenever any file changes -// CLI --auto-watch --no-auto-watch -autoWatch = true; - -// Start these browsers, currently available: -// - Chrome -// - ChromeCanary -// - Firefox -// - Opera -// - Safari (only Mac) -// - PhantomJS -// - IE (only Windows) -// CLI --browsers Chrome,Firefox,Safari -browsers = ['Chrome']; //, 'Firefox']; - -// If browser does not capture in given timeout [ms], kill it -// CLI --capture-timeout 5000 -captureTimeout = 5000; - -// Auto run tests on start (when browsers are captured) and exit -// CLI --single-run --no-single-run -singleRun = false; - -// report which specs are slower than 500ms -// CLI --report-slower-than 500 -reportSlowerThan = 500; + /** + * The list of browsers to launch to test ondest * default, but other browser names include: + * Chrome, ChromeCanary, Firefox, Opera, Safari, PhantomJS + * + * Note that you can also use the executable name of the browser, like "chromium" + * or "firefox", but that these vary based on your operating system. + * + * You may also leave this blank and manually navigate your browser to + * http://localhost:9018/ when you're running tests. The window/tab can be left + * open and the tests will automatically occur there during the build. This has + * the aesthetic advantage of not launching a browser every time you save. + */ + browsers: [ + 'Chrome' + ] + }); +}; diff --git a/test/unit/angular-carousel.js b/test/unit/angular-carousel.js index 99c975d..0606bf5 100644 --- a/test/unit/angular-carousel.js +++ b/test/unit/angular-carousel.js @@ -5,14 +5,14 @@ describe('carousel', function () { var scope, $compile, $sandbox; - +/* //$('body').append(""); $('body').append(""); - +*/ //console.log(document.location); beforeEach( module('angular-carousel') @@ -21,15 +21,15 @@ describe('carousel', function () { beforeEach(inject(function ($rootScope, _$compile_) { scope = $rootScope; $compile = _$compile_; - $('body').css({ - padding: 0, - margin:0 - }); - $sandbox = $('
    ').appendTo($('body')); + // $('body').css({ + // padding: 0, + // margin:0 + // }); + // $sandbox = $('
    ').appendTo($('body')); })); afterEach(function() { - $sandbox.remove(); + //$sandbox.remove(); scope.$destroy(); }); @@ -61,8 +61,8 @@ describe('carousel', function () { if (options.useIndex) tpl += ' rn-carousel-index="' + options.useIndex + '" '; tpl += '>
  • {{ item.text }}
  • '; angular.extend(scope, sampleData.scope); - var $element = $(tpl).appendTo($sandbox); - $element = $compile($element)(scope); + // var $element = $(tpl).appendTo($sandbox); + var $element = $compile(tpl)(scope); scope.$digest(); return $element; } @@ -79,6 +79,10 @@ describe('carousel', function () { expect(curMatrix).toBe(expectedMatrix); } + it('should load test', function() { + expect(1).toBe(1); + }); +/* describe('directive', function () { it('should add a wrapper div around the ul/li', function () { var elm = compileTpl(); @@ -565,5 +569,6 @@ describe('carousel', function () { // }); //}); - +*/ }); + diff --git a/test/unit/collectionManager.js b/test/unit/collectionManager.js deleted file mode 100644 index b590825..0000000 --- a/test/unit/collectionManager.js +++ /dev/null @@ -1,227 +0,0 @@ -/*global angular, console, describe, it, expect, beforeEach, inject */ - -//--- SPECS ------------------------- -describe("CollectionManager", function() { - var collec1 = null, - collec2 = null; - var sampleCollectionOptions = { - items: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - index: 1 - }; - beforeEach(module('angular-carousel')); - - var CollectionManagerService; - beforeEach(inject(function(CollectionManager) { - CollectionManagerService = CollectionManager; - })); - - describe("basic", function() { - beforeEach(function() { - collec1 = CollectionManagerService.create(); - collec2 = CollectionManagerService.create(sampleCollectionOptions); - }); - it("initialise an empty list", function() { - expect(collec1.items).toEqual([]); - expect(collec2.items).toEqual(sampleCollectionOptions.items); - }); - it("initialise index correctly", function() { - expect(collec1.index).toBe(0); - expect(collec2.index).toBe(sampleCollectionOptions.index); - }); - describe('next()/prev()', function() { - it("does not change index if has no items", function() { - collec1.next(); - expect(collec1.index).toBe(0); - collec1.prev(); - expect(collec1.index).toBe(0); - }); - it("update index if has items", function() { - collec2.next(); - expect(collec2.index).toBe(sampleCollectionOptions.index + 1); - collec2.prev(); - expect(collec2.index).toBe(sampleCollectionOptions.index); - }); - it("stops at first item", function() { - collec2.prev(); - collec2.prev(); - collec2.prev(); - collec2.prev(); - collec2.prev(); - collec2.prev(); - expect(collec2.index).toBe(0); - }); - it("stops at last item", function() { - for (var i=0;i Date: Sun, 5 Jan 2014 01:55:10 +0100 Subject: [PATCH 004/159] chore(grunt): fix karma config --- Gruntfile.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 9eb38c3..c799311 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -98,6 +98,7 @@ module.exports = function(grunt) { }, unit: { port: 7101, + singleRun: false, background: true }, continuous: { @@ -107,7 +108,7 @@ module.exports = function(grunt) { watch: { dev: { files: ['<%= dirs.src %>/**'], - tasks: ['build'] + tasks: ['build', 'karma:unit:run'] }, test: { files: ['test/unit/**'], @@ -127,14 +128,10 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-karma'); - // Test tasks. - grunt.registerTask('test', ['jshint', 'karma:unit']); - // Build task. - grunt.registerTask('quickbuild', ['jshint', 'concat', 'uglify', 'autoprefixer', 'cssmin']); - grunt.registerTask('build', ['quickbuild', 'test']); + grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'autoprefixer', 'cssmin']); // Default task. - grunt.registerTask('default', ['build', 'connect', 'watch']); + grunt.registerTask('default', ['build', 'connect', 'karma:unit', 'watch']); }; From cbed49bdb6564a6ddfc3235a4dad486320935fbc Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 5 Jan 2014 01:57:50 +0100 Subject: [PATCH 005/159] feature(indicators): optional clickable indicators --- TODO | 4 +-- dist/angular-carousel.css | 21 +++++++++++++++ dist/angular-carousel.js | 34 +++++++++++++++++++----- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 2 +- index.html | 11 +++++--- src/css/angular-carousel.css | 20 ++++++++++++++ src/directives/rn-carousel-indicators.js | 2 +- src/directives/rn-carousel.js | 32 ++++++++++++++++++---- 9 files changed, 108 insertions(+), 20 deletions(-) diff --git a/TODO b/TODO index d7220a9..526fda7 100644 --- a/TODO +++ b/TODO @@ -11,8 +11,8 @@ Carousel v2: Buffering: ✔ should optionnaly buffer the carousel DOM @done (14-01-04 20:22) Indicators: - ☐ should have optional indicators - ☐ indicators should be clickable + ✔ should have optional indicators @done (14-01-05 01:56) + ✔ indicators should be clickable @done (14-01-05 01:56) ☐ indicators should be customisable Animations: ☐ should have some builtin animations diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index 35b2776..8a02df3 100644 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -25,3 +25,24 @@ use autoprefixer to build the final CSS -ms-backface-visibility: hidden; backface-visibility: hidden; } + +/* indicator */ + +.rn-carousel-indicator { + width: 100%; + text-align:center; + position:relative; + bottom: 20px; + height:20px; + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.6); +} +.rn-carousel-indicator span { + padding: 0 5px; + color: #333; + -webkit-transition: color .2s ease-out; + transition: color .2s ease-out; +} +.rn-carousel-indicator .active { + color:white; +} diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index dc7ee26..445fcf7 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -28,7 +28,7 @@ angular.module('angular-carousel') index: '=' }, template: '' }; }]); @@ -38,7 +38,7 @@ angular.module('angular-carousel') angular.module('angular-carousel') - .directive('rnCarousel', ['$swipe', '$window', '$document', '$parse', function($swipe, $window, $document, $parse) { + .directive('rnCarousel', ['$swipe', '$window', '$document', '$parse', '$compile', function($swipe, $window, $document, $parse, $compile) { // internal ids to allow multiple instances var carouselId = 0, // used to compute the sliding speed @@ -98,7 +98,7 @@ angular.module('angular-carousel') slidesCount = tElement.children().length; } - return function(scope, iElement, iAttributes) { + return function(scope, iElement, iAttributes, containerCtrl) { carouselId++; @@ -113,9 +113,22 @@ angular.module('angular-carousel') timestamp; // add a wrapper div that will hide the overflow - var carousel = iElement.wrap(""), + var carousel = iElement.wrap(""), container = carousel.parent(); + // enable carousel indicator + if (angular.isDefined(iAttributes.rnCarouselIndicator)) { + updateIndicatorArray(); + scope.$watch('carouselIndex', function(newValue) { + scope.indicatorIndex = newValue; + }); + scope.$watch('indicatorIndex', function(newValue) { + goToSlide(newValue, true); + }); + var indicator = $compile("")(scope); + container.append(indicator); + } + scope.carouselBufferIndex = 0; scope.carouselBufferSize = 5; scope.carouselIndex = 0; @@ -145,8 +158,8 @@ angular.module('angular-carousel') // watch the given collection if (isRepeatBased) { scope.$watchCollection(repeatCollection, function(newValue, oldValue) { - //console.log('collection updated', repeatCollection, arguments); slidesCount = newValue.length; + updateIndicatorArray(); if (!containerWidth) updateContainerWidth(); goToSlide(scope.carouselIndex); }); @@ -154,6 +167,13 @@ angular.module('angular-carousel') updateContainerWidth(); } + function updateIndicatorArray() { + // generate an arrat to be used by the indicators + var items = []; + for (var i = 0; i < slidesCount; i++) items[i] = i; + scope.carouselIndicatorArray = items; + } + function getCarouselWidth() { // container.css('width', 'auto'); var slides = carousel.children(); @@ -312,8 +332,10 @@ angular.module('angular-carousel') var minMove = getAbsMoveTreshold(), currentOffset = (scope.carouselIndex * containerWidth), absMove = currentOffset - destination, + slidesMove = -Math[absMove>=0?'ceil':'floor'](absMove / containerWidth), shouldMove = Math.abs(absMove) > minMove, - moveOffset = shouldMove?(absMove<0)?1:-1:0; + moveOffset = shouldMove?slidesMove:0; + destination = (moveOffset + scope.carouselIndex) * containerWidth; amplitude = destination - offset; timestamp = Date.now(); diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index caa0047..1bbf4ad 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden}.rn-carousel-slides{position:relative;white-space:nowrap;overflow:visible;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden} \ No newline at end of file +.rn-carousel-container{overflow:hidden}.rn-carousel-slides{position:relative;white-space:nowrap;overflow:visible;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;position:relative;bottom:20px;height:20px;background-color:#000;background-color:rgba(0,0,0,.6)}.rn-carousel-indicator span{padding:0 5px;color:#333;-webkit-transition:color .2s ease-out;transition:color .2s ease-out}.rn-carousel-indicator .active{color:#fff} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 13a4027..295eb37 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse",function(a,b,c,d){var e=0,f=75,g=.05,h=3;return{restrict:"A",scope:!0,compile:function(i,j){var k,l,m=i.children()[0].attributes,n=!1,o=!1,p=0,q=!1;if(i.addClass("rn-carousel-slides"),i.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=m[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(k=c[1],l=c[2],k)return angular.isDefined(j.rnCarouselBuffered)&&(o=!0,b.value=k+" in "+l+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),n=!0,!1}return!0}),!n){{i.children()}p=i.children().length}return function(i,j,k){function m(){var a=M.children();return E=0===a.length?M[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function r(){N.css("width",m()+"px")}function s(a){isNaN(a)&&(a=i.carouselIndex*E),L=a;var b=-Math.round(L);b+=i.carouselBufferIndex*E,M[0].style[F]="translate3d("+b+"px, 0, 0)"}function t(){var a,b;I&&(a=Date.now()-K,b=I*Math.exp(-a/f),b>h||-h>b?(s(J-b),requestAnimationFrame(t)):w(J/E))}function u(a){return a>=p?p:0>=a?0:a}function v(){var a=0,b=(i.carouselBufferSize-1)/2;o&&(a=i.carouselIndex<=b?0:i.carouselIndex>p-i.carouselBufferSize?p-i.carouselBufferSize:i.carouselIndex-b),i.carouselBufferIndex=a}function w(a,b){return isNaN(a)&&(a=i.carouselIndex),b?(L=a*E,C(null,null,!0),void 0):(i.carouselIndex=u(a),v(),"$apply"!==i.$$phase&&"$digest"!==i.$$phase&&(q?i.$apply():i.$digest()),s(),void 0)}function x(){return g*E}function y(a){C({x:a.clientX,y:a.clientY},a)}function z(a){var b=a;return 0===i.carouselIndex?b=Math.max(-x(),b):i.carouselIndex===p-1&&(b=Math.min((p-1)*E+x(),b)),b}function A(a,b){return c.bind("mouseup",y),G=!0,H=a.x,I=0,K=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function B(a,b){var c,d;return G&&(c=a.x,d=H-c,(d>2||-2>d)&&(H=c,requestAnimationFrame(function(){s(z(L+d))}))),b.preventDefault(),b.stopPropagation(),!1}function C(a,b,d){c.unbind("mouseup",y),G=!1,J=L;var e=x(),f=i.carouselIndex*E,g=f-J,h=Math.abs(g)>e,j=h?0>g?1:-1:0;return J=(j+i.carouselIndex)*E,I=J-L,K=Date.now(),d&&(I=L-f),requestAnimationFrame(t),b&&(b.preventDefault(),b.stopPropagation()),!1}function D(){alert("onOrientationChange"),r(),w()}e++;var E,F,G,H,I,J,K,L=0,M=j.wrap(""),N=M.parent();if(i.carouselBufferIndex=0,i.carouselBufferSize=5,i.carouselIndex=0,k.rnCarouselIndex){var O=d(k.rnCarouselIndex);angular.isFunction(O.assign)?(i.$watch("carouselIndex",function(a){O.assign(i.$parent,a)}),i.carouselIndex=O(i),i.$parent.$watch(O,function(a){void 0!==a&&w(a,!0)}),q=!0):isNaN(k.rnCarouselIndex)||(i.carouselIndex=parseInt(k.rnCarouselIndex,10))}n?i.$watchCollection(l,function(a){p=a.length,E||r(),w(i.carouselIndex)}):r(),a.bind(M,{start:A,move:B,end:C,cancel:function(a){C({},a)}}),w(i.carouselIndex),F="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(F=b,!1):!0});var P=angular.element(b);P.bind("orientationchange",D),i.$on("$destroy",function(){c.unbind("mouseup",y),P.unbind("orientationchange",D)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return a.slice(b,b+c)}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function t(){P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e,k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){alert("onOrientationChange"),t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=a.length,n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return a.slice(b,b+c)}})}(); \ No newline at end of file diff --git a/index.html b/index.html index 9ff04ee..02b98da 100644 --- a/index.html +++ b/index.html @@ -67,6 +67,9 @@ .ng-cloak { display:none; } + .center { + text-align:center; + } Fork me on GitHub @@ -92,7 +95,7 @@

    ngRepeat demo (buffered carousel)

    template-based demo

    -
      +
      • This is a standard template
        slide #1
        @@ -111,8 +114,8 @@

        template-based demo

      -

      buffered ngRepeat carousel with custom controls

      -
        +

        buffered ngRepeat carousel with indicator and custom controls

        +
        • {{ slide.label }} / {{ slides2.length }} @@ -135,7 +138,7 @@

          Other demos



        - + diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 7e10038..0bc5b52 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -123,7 +123,12 @@ // watch the given collection if (isRepeatBased) { scope.$watchCollection(repeatCollection, function(newValue, oldValue) { - slidesCount = newValue.length; + slidesCount = 0; + if (angular.isArray(newValue)) { + slidesCount = newValue.length; + } else if (angular.isObject(newValue)) { + slidesCount = Object.keys(newValue).length; + } updateIndicatorArray(); if (!containerWidth) updateContainerWidth(); goToSlide(scope.carouselIndex); diff --git a/src/directives/sliceFilter.js b/src/directives/sliceFilter.js index e456f2f..f3121bf 100644 --- a/src/directives/sliceFilter.js +++ b/src/directives/sliceFilter.js @@ -5,7 +5,12 @@ .filter('carouselSlice', function() { return function(collection, start, size) { - return collection.slice(start, start + size); + if (angular.isArray(collection)) { + return collection.slice(start, start + size); + } else if (angular.isObject(collection)) { + // dont try to slice collections :) + return collection; + } }; }); From 7235a59bfc6e30ba8faa9d3fe159220f3b7c1368 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 5 Jan 2014 02:37:20 +0100 Subject: [PATCH 008/159] chore(bower): change bower package name --- README.md | 2 +- bower.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8e9d4a6..fd32c27 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Proudly brought to you by the [@revolunet](http://twitter.com/revolunet) team. ## Usage : - 1. If you use bower, just `bower install angular-carousel`. + 1. If you use bower, just `bower install angular-rn-carousel`. 2. If not, add `angular-carousel.css`, `angular-carousel.js` to your code: ```html diff --git a/bower.json b/bower.json index b02d4e9..4f10f79 100644 --- a/bower.json +++ b/bower.json @@ -1,8 +1,8 @@ { "author": "revolunet", - "name": "angular-carousel", + "name": "angular-rn-carousel", "description": "Mobile friendly AngularJS carousel", - "version": "0.1.0", + "version": "0.1.1", "homepage": "https://github.com/revolunet/angular-carousel", "repository": { "type": "git", diff --git a/package.json b/package.json index 3a37108..2e10315 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.0.9", + "version": "0.1.1", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From 7979a877ce700d94874d287574d3709393bf1b95 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 5 Jan 2014 03:22:27 +0100 Subject: [PATCH 009/159] docs: update README --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fd32c27..b8f048b 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ Proudly brought to you by the [@revolunet](http://twitter.com/revolunet) team. ## Usage : - 1. If you use bower, just `bower install angular-rn-carousel`. - 2. If not, add `angular-carousel.css`, `angular-carousel.js` to your code: + 1. If you use bower, just `bower install angular-rn-carousel`. If not, download files [from the github repo](./dist) + 2. Add `angular-carousel.css`, `angular-carousel.js` to your code: ```html - - - - + + + + ``` 2. Add a dependency to the `angular-carousel` module in your application. @@ -32,6 +32,7 @@ angular.module('MyApp', ['angular-carousel']);
      ``` + 4. You can also use `rn-carousel` without ng-repeat ;) ```html
        @@ -43,9 +44,10 @@ angular.module('MyApp', ['angular-carousel']); ## Features : - Mobile friendly, tested on webkit+firefox - - CSS 3D transformations with GPU accel + - use CSS 3D transformations and `requestAnimationFrame`. - DOM buffering - index data-binding + - optional indicators ### Regular carousel : - `rn-carousel-index` two way binding to control the carousel position. From fd1ef4943e52fa167860c520ec9174ebf97aa069 Mon Sep 17 00:00:00 2001 From: ADmad Date: Sun, 5 Jan 2014 12:46:01 +0530 Subject: [PATCH 010/159] Removed debugging code and minor formatting change. --- src/directives/rn-carousel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 0bc5b52..a92e940 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -167,7 +167,7 @@ if (isNaN(x)) { x = scope.carouselIndex * containerWidth; } - + offset = x; var move = -Math.round(offset); move += (scope.carouselBufferIndex * containerWidth); @@ -274,6 +274,7 @@ event.stopPropagation(); return false; } + function swipeMove(coords, event) { //console.log('swipeMove', coords, event); var x, delta; @@ -291,7 +292,7 @@ event.stopPropagation(); return false; } - + function swipeEnd(coords, event, forceAnimation) { //console.log('swipeEnd', 'scope.carouselIndex', scope.carouselIndex); $document.unbind('mouseup', documentMouseUpEvent); @@ -345,9 +346,8 @@ }); function onOrientationChange() { - alert('onOrientationChange'); - updateContainerWidth(); - goToSlide(); + updateContainerWidth(); + goToSlide(); } // handle orientation change From 8b65dd3085e812651c6b699a188d2976441d10a2 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Mon, 6 Jan 2014 09:49:32 +0100 Subject: [PATCH 011/159] chore(bower): bump version --- bower.json | 2 +- dist/angular-carousel.js | 12 ++++++------ dist/angular-carousel.min.js | 4 ++-- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bower.json b/bower.json index 4f10f79..edc601e 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "author": "revolunet", "name": "angular-rn-carousel", "description": "Mobile friendly AngularJS carousel", - "version": "0.1.1", + "version": "0.1.3", "homepage": "https://github.com/revolunet/angular-carousel", "repository": { "type": "git", diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e383439..c1702b4 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.0.9 - 2014-01-05 + * @version v0.1.3 - 2014-01-06 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -202,7 +202,7 @@ angular.module('angular-carousel') if (isNaN(x)) { x = scope.carouselIndex * containerWidth; } - + offset = x; var move = -Math.round(offset); move += (scope.carouselBufferIndex * containerWidth); @@ -309,6 +309,7 @@ angular.module('angular-carousel') event.stopPropagation(); return false; } + function swipeMove(coords, event) { //console.log('swipeMove', coords, event); var x, delta; @@ -326,7 +327,7 @@ angular.module('angular-carousel') event.stopPropagation(); return false; } - + function swipeEnd(coords, event, forceAnimation) { //console.log('swipeEnd', 'scope.carouselIndex', scope.carouselIndex); $document.unbind('mouseup', documentMouseUpEvent); @@ -380,9 +381,8 @@ angular.module('angular-carousel') }); function onOrientationChange() { - alert('onOrientationChange'); - updateContainerWidth(); - goToSlide(); + updateContainerWidth(); + goToSlide(); } // handle orientation change diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 09b0e71..bf9d7ec 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.0.9 - 2014-01-05 + * @version v0.1.3 - 2014-01-06 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(G)}function t(){P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e,k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){alert("onOrientationChange"),t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=0,angular.isArray(a)?q=a.length:angular.isObject(a)&&(q=Object.keys(a).length),n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(G)}function t(){P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e,k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=0,angular.isArray(a)?q=a.length:angular.isObject(a)&&(q=Object.keys(a).length),n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index 2e10315..b2f862f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.1.1", + "version": "0.1.3", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From 2346da26e83466ce1a5bebd594d77b9cae0ecdd0 Mon Sep 17 00:00:00 2001 From: jtredoux Date: Tue, 7 Jan 2014 17:10:04 +0200 Subject: [PATCH 012/159] fix for #83: dynamic sizing --- src/directives/rn-carousel.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index a92e940..386ab94 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -158,6 +158,7 @@ function updateContainerWidth() { // force the carousel container width to match the first slide width + container.css('width', '100%'); container.css('width', getCarouselWidth() + 'px'); } @@ -353,12 +354,12 @@ // handle orientation change var winEl = angular.element($window); winEl.bind('orientationchange', onOrientationChange); - //winEl.bind('resize', onOrientationChange); + winEl.bind('resize', onOrientationChange); scope.$on('$destroy', function() { $document.unbind('mouseup', documentMouseUpEvent); winEl.unbind('orientationchange', onOrientationChange); - // winEl.unbind('resize', onOrientationChange); + winEl.unbind('resize', onOrientationChange); }); }; From 0f0d8a886410d843edb5b3654afcc6770d5ea312 Mon Sep 17 00:00:00 2001 From: Gaku Ueda Date: Tue, 7 Jan 2014 13:51:40 -0800 Subject: [PATCH 013/159] Prevent slide range overrun by checking the slide boundary. --- src/directives/rn-carousel.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index a92e940..233868c 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -304,8 +304,15 @@ currentOffset = (scope.carouselIndex * containerWidth), absMove = currentOffset - destination, slidesMove = -Math[absMove>=0?'ceil':'floor'](absMove / containerWidth), - shouldMove = Math.abs(absMove) > minMove, - moveOffset = shouldMove?slidesMove:0; + shouldMove = Math.abs(absMove) > minMove; + + if ((slidesMove + scope.carouselIndex) >= slidesCount ) { + slidesMove = slidesCount - 1 - scope.carouselIndex; + } + if ((slidesMove + scope.carouselIndex) < 0) { + slidesMove = -scope.carouselIndex; + } + var moveOffset = shouldMove?slidesMove:0; destination = (moveOffset + scope.carouselIndex) * containerWidth; amplitude = destination - offset; From 393ef3f1acf5c52fe7005df6935e07a553998b6a Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Tue, 7 Jan 2014 23:12:18 +0100 Subject: [PATCH 014/159] chore: todo update --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index e717d25..9e11f6c 100644 --- a/TODO +++ b/TODO @@ -17,6 +17,7 @@ Carousel v2: Animations: ☐ should have some builtin animations ☐ should be able to customise animations + ☐ animation should occur on slides instead of container Bugs: ✔ bug when rn-carousel-index change while animation from outside @done (14-01-05 02:19) ☐ handle touch cancel @@ -30,5 +31,6 @@ Carousel v2: ✔ update grunt @done (14-01-04 22:09) ✔ add autoprefixer @done (14-01-04 22:09) ☐ template with code samples for the demo page + ☐ automate version bump Docs: ✔ README update @done (14-01-05 02:19) From b7d8f4558ff2331ed25949cbb552793836321197 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 8 Jan 2014 00:41:09 +0100 Subject: [PATCH 015/159] fix: fix initial positionning when index>0 --- dist/angular-carousel.js | 25 ++++++++++++++++++------- dist/angular-carousel.min.js | 4 ++-- src/directives/rn-carousel.js | 7 +++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index c1702b4..cb37a2d 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.1.3 - 2014-01-06 + * @version v0.1.3 - 2014-01-08 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -193,6 +193,7 @@ angular.module('angular-carousel') function updateContainerWidth() { // force the carousel container width to match the first slide width + container.css('width', '100%'); container.css('width', getCarouselWidth() + 'px'); } @@ -339,8 +340,15 @@ angular.module('angular-carousel') currentOffset = (scope.carouselIndex * containerWidth), absMove = currentOffset - destination, slidesMove = -Math[absMove>=0?'ceil':'floor'](absMove / containerWidth), - shouldMove = Math.abs(absMove) > minMove, - moveOffset = shouldMove?slidesMove:0; + shouldMove = Math.abs(absMove) > minMove; + + if ((slidesMove + scope.carouselIndex) >= slidesCount ) { + slidesMove = slidesCount - 1 - scope.carouselIndex; + } + if ((slidesMove + scope.carouselIndex) < 0) { + slidesMove = -scope.carouselIndex; + } + var moveOffset = shouldMove?slidesMove:0; destination = (moveOffset + scope.carouselIndex) * containerWidth; amplitude = destination - offset; @@ -366,8 +374,11 @@ angular.module('angular-carousel') } }); - // initialise first slide - goToSlide(scope.carouselIndex); + // initialise first slide only if no binding + // if so, the binding will trigger the first init + if (!isIndexBound) { + goToSlide(scope.carouselIndex); + } // detect supported CSS property transformProperty = 'transform'; @@ -388,12 +399,12 @@ angular.module('angular-carousel') // handle orientation change var winEl = angular.element($window); winEl.bind('orientationchange', onOrientationChange); - //winEl.bind('resize', onOrientationChange); + winEl.bind('resize', onOrientationChange); scope.$on('$destroy', function() { $document.unbind('mouseup', documentMouseUpEvent); winEl.unbind('orientationchange', onOrientationChange); - // winEl.unbind('resize', onOrientationChange); + winEl.unbind('resize', onOrientationChange); }); }; diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index bf9d7ec..4c9fe83 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.1.3 - 2014-01-06 + * @version v0.1.3 - 2014-01-08 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(G)}function t(){P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e,k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=0,angular.isArray(a)?q=a.length:angular.isObject(a)&&(q=Object.keys(a).length),n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(G)}function t(){P.css("width","100%"),P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e;h+j.carouselIndex>=q&&(h=q-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=0,angular.isArray(a)?q=a.length:angular.isObject(a)&&(q=Object.keys(a).length),n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),r||y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),S.bind("resize",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F),S.unbind("resize",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index e246da2..2b1936b 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -339,8 +339,11 @@ } }); - // initialise first slide - goToSlide(scope.carouselIndex); + // initialise first slide only if no binding + // if so, the binding will trigger the first init + if (!isIndexBound) { + goToSlide(scope.carouselIndex); + } // detect supported CSS property transformProperty = 'transform'; From a223c24787580d51166d111ca6efe76f22a4050c Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 8 Jan 2014 00:41:32 +0100 Subject: [PATCH 016/159] docs: add some more demos --- TODO | 1 + demo/demo.css | 118 ++++++++++++++++++++++++++++++++++++ index.html | 162 +++++++++++++++++++++++--------------------------- 3 files changed, 193 insertions(+), 88 deletions(-) create mode 100644 demo/demo.css diff --git a/TODO b/TODO index 9e11f6c..8b248c1 100644 --- a/TODO +++ b/TODO @@ -21,6 +21,7 @@ Carousel v2: Bugs: ✔ bug when rn-carousel-index change while animation from outside @done (14-01-05 02:19) ☐ handle touch cancel + ✔ initial index position not respected @done (14-01-07 23:51) Advanced: ☐ optional cycle ☐ infinite carousels with slide generators diff --git a/demo/demo.css b/demo/demo.css new file mode 100644 index 0000000..6426a8a --- /dev/null +++ b/demo/demo.css @@ -0,0 +1,118 @@ +html, body { + height:100%; + padding:0; + margin:0; +} +body { + margin: 0; + background: #333; + color:white; + padding: 10px; +} +a { + color:white; +} +* { + font-family: 'Droid Sans', sans-serif; +} +h1 { + margin-top: 5px; +} +h3 { + font-size:30px; + margin: 30px 0 10px 0; +} +.my-slider { + width: 450px; + height: 300px; + font-size:0; +} +.my-slider li { + box-sizing: border-box; + font-size:30px; + position:relative; +} +.my-slider li div.debug { + box-sizing: border-box; + position:absolute; + bottom:0; + height:50px; + background:rgba(0,0,0,0.7); + color:white; + font-size:12px; + width:100%; + padding:5px; +} +.my-slider.standard li { + text-align:center; + padding:20px; + font-size:20px; +} +.big { + margin-top:30px; + width:100%; + font-size:30px; +} +.controls { + margin-top:-15px; + width:450px; + text-align: center; +} +.ng-cloak { + display:none; +} +.center { + text-align:center; +} +.thumbs { + width:450px; + text-align:center; +} +.thumb { + display: inline-block; + background-size:cover; + border:1px solid transparent; + margin:2px 4px; + width:60px; + height:40px; + transition: border 0.2s ease-in; +} +.is-active { + border:1px solid red; +} +.details { + color:white; + font-size:12px; + margin-bottom:10px; +} +.button{ + display: inline-block; + text-decoration: none; + font: bold 12px/12px HelveticaNeue, Arial; + padding: 8px 11px; + color: #555; + border: 1px solid #dedede; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + cursor:pointer; +} +.button:disabled { + cursor: default !important; + color: #aaa !important; +} +.button.grey{ + background: #bdbdbd; + background: -webkit-gradient(linear, left top, left bottom, from(#cacaca), to(#aeaeae)); /* WebKit */ + background: -moz-linear-gradient(top, #cacaca, #aeaeae); + border-color: #b5b5b5 #a1a1a1 #8f8f8f; + color: #555; + text-shadow: 0 1px 0 #d4d4d4; +} +.button.grey:hover{ + background: #c2c2c2; + background: -webkit-gradient(linear, left top, left bottom, from(#bcbcbc), to(#c2c2c2)); /* WebKit */ + background: -moz-linear-gradient(top, #bcbcbc, #c2c2c2); + border-color: #989898 #8e8e8e #878787; + text-shadow: 0 1px 0 #dadada; +} diff --git a/index.html b/index.html index 157d540..e786753 100644 --- a/index.html +++ b/index.html @@ -1,78 +1,13 @@ - - - angular-carousel demo - - - - + + + angular-carousel demo + + + + + Fork me on GitHub @@ -81,10 +16,14 @@

        AngularJS Touch Carousel

        Transform your ng-repeat or DOM nodes in a mobile-friendly carousel just by adding a 'rn-carousel' attribute to your HTML; AngularJS directives FTW :)

        Carousels are data-bound to your ngRepeat collections and can be DOM buffered (good for performance)

        - Swipe these demos with your mouse or finger : + Swipe these demos with your mouse or finger

        ngRepeat demo (buffered carousel)

        +
        A simple buffered ng-repeat with a custom template. +
        + Swipe 50 slides with only 5 slides in the DOM +
        • @@ -97,6 +36,10 @@

          ngRepeat demo (buffered carousel)

        template-based demo

        +
        Various blocks automagically converted to a carousel. +
        + Just add rn-carousel-indicator to display clickable indicators +
        • This is a standard template @@ -116,11 +59,21 @@

          template-based demo

        +

        Standard carousel with thumbs navigation

        +
        This one has an initial index and the thumbs controls the rn-carousel-index binding
        +
          +
        • +
        +
        +
        +
        +

        buffered ngRepeat carousel with custom controls

        +
        Custom controls demo, just update the rn-carousel-index index binding
          -
        • +
        • - {{ slide.label }} / {{ slides2.length }} + {{ slide.label }} / {{ slides4.length }}
          carouselIndex: {{ carouselIndex }}
          carouselBufferIndex: {{ carouselBufferIndex }}
          @@ -128,26 +81,38 @@

          buffered ngRepeat carousel with custom controls

        - - {{ slideIndex + 1 }} / {{ slides2.length }} - - + + {{ slideIndex + 1 }} / {{ slides4.length }} + +

        object-based ngRepeat carousel with indicators

        -
          +
          Use the object-based ngRepeat syntax. (not compatible with buffering)
          +
          • {{ label }}
          +

          togglable carousel via ng-if

          +
          If you use ng-if, be sure to use the dot-notation syntax for the index binding.
          + +

          + +
            +
          • +
            #{{ $index + 1 }}
            +
          • +
          +

          Other demos



          - + From 4b5338878a8d88e9e220170680114bdb21f89e68 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 8 Jan 2014 00:41:52 +0100 Subject: [PATCH 017/159] chore: bump version --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index edc601e..7469022 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "author": "revolunet", "name": "angular-rn-carousel", "description": "Mobile friendly AngularJS carousel", - "version": "0.1.3", + "version": "0.1.4", "homepage": "https://github.com/revolunet/angular-carousel", "repository": { "type": "git", diff --git a/package.json b/package.json index b2f862f..b6c304a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.1.3", + "version": "0.1.4", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From 7c628dead3a09bb0b433e7dafbe66515ec0e6bd2 Mon Sep 17 00:00:00 2001 From: Gaku Ueda Date: Wed, 8 Jan 2014 06:06:40 -0800 Subject: [PATCH 018/159] Made slideCount per instance. --- src/directives/rn-carousel.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 2b1936b..453cc8c 100644 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -57,11 +57,6 @@ } return true; }); - if (!isRepeatBased) { - // basic template based carousel - var liChilds = tElement.children(); - slidesCount = tElement.children().length; - } return function(scope, iElement, iAttributes, containerCtrl) { @@ -74,6 +69,7 @@ amplitude, offset = 0, destination, + slidesCount = 0, // javascript based animation easing timestamp; @@ -134,6 +130,7 @@ goToSlide(scope.carouselIndex); }); } else { + slidesCount = iElement.children().length; updateContainerWidth(); } From 46b021dada76462071b78681e2344b1dfb6c8929 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 15 Jan 2014 00:22:58 +0100 Subject: [PATCH 019/159] docs: add requestAnimFrame link for older androids --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b8f048b..67b89b9 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ angular.module('MyApp', ['angular-carousel']);
        ``` +**NOTE :** if you use older Android (<4) please include the [requestAnimationFrame polyfill](https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js) in your application. + ## Features : - Mobile friendly, tested on webkit+firefox - use CSS 3D transformations and `requestAnimationFrame`. From 77ae79f194ff12a5a65a7228dace4629430e1f8a Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 13:50:49 -0600 Subject: [PATCH 020/159] adding controls and sass building --- .gitignore | 1 + Gruntfile.js | 17 +++- dist/angular-carousel.css | 110 ++++++++++++++++--------- dist/angular-carousel.js | 44 ++++++++-- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 +- package.json | 1 + src/css/angular-carousel.css | 43 ---------- src/css/angular-carousel.scss | 110 +++++++++++++++++++++++++ src/directives/rn-carousel-controls.js | 24 ++++++ src/directives/rn-carousel.js | 11 ++- 11 files changed, 268 insertions(+), 99 deletions(-) mode change 100644 => 100755 Gruntfile.js mode change 100644 => 100755 dist/angular-carousel.css mode change 100644 => 100755 dist/angular-carousel.js mode change 100644 => 100755 package.json delete mode 100644 src/css/angular-carousel.css create mode 100755 src/css/angular-carousel.scss create mode 100755 src/directives/rn-carousel-controls.js mode change 100644 => 100755 src/directives/rn-carousel.js diff --git a/.gitignore b/.gitignore index 55c5256..8260c04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.sass-cache *.DS_Store node_modules bower_components diff --git a/Gruntfile.js b/Gruntfile.js old mode 100644 new mode 100755 index c799311..88aa0f9 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,6 +52,18 @@ module.exports = function(grunt) { dest: '<%= dirs.dest %>/<%= pkg.name %>.js' } }, + sass: { + dist: { + files: [{ + expand: true, + cwd: './src/css', + src: ['*.scss'], + dest: './dist', + ext: '.css' + }] + } + }, + cssmin: { combine: { files: { @@ -59,6 +71,7 @@ module.exports = function(grunt) { } } }, + uglify: { options: { banner: '<%= meta.banner %>' @@ -114,7 +127,6 @@ module.exports = function(grunt) { files: ['test/unit/**'], tasks: ['karma:unit:run'] } - } }); @@ -123,13 +135,14 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-karma'); // Build task. - grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'autoprefixer', 'cssmin']); + grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'autoprefixer', 'sass', 'cssmin']); // Default task. grunt.registerTask('default', ['build', 'connect', 'karma:unit', 'watch']); diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css old mode 100644 new mode 100755 index 8a02df3..186f527 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -1,48 +1,76 @@ -/* -generic styles applied to any carousel -use autoprefixer to build the final CSS -*/ +/* variables */ +/* mixins */ +/* general */ .rn-carousel-container { - overflow: hidden; -} + overflow: hidden; + position: relative; + padding-bottom: 20px; } + .rn-carousel-slides { - position: relative; - white-space: nowrap; - overflow: visible; - -webkit-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - padding: 0; - margin: 0; -} -.rn-carousel-slide { - white-space: normal; - vertical-align:top; - display: inline-block; - width: 100%; - height: 100%; - -webkit-backface-visibility: hidden; - -ms-backface-visibility: hidden; - backface-visibility: hidden; -} + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + position: relative; + white-space: nowrap; + overflow: visible; + padding: 0; + margin: 0; } -/* indicator */ +.rn-carousel-slide { + white-space: normal; + vertical-align: top; + display: inline-block; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; } +/* indicators */ .rn-carousel-indicator { width: 100%; - text-align:center; - position:relative; - bottom: 20px; - height:20px; - background-color: rgb(0, 0, 0); + text-align: center; + position: relative; + height: 20px; + background-color: black; background-color: rgba(0, 0, 0, 0.6); -} -.rn-carousel-indicator span { - padding: 0 5px; - color: #333; - -webkit-transition: color .2s ease-out; - transition: color .2s ease-out; -} -.rn-carousel-indicator .active { - color:white; -} + position: absolute; + bottom: 0; } + .rn-carousel-indicator span { + -webkit-transition: color 0.2s ease-out; + -moz-transition: color 0.2s ease-out; + -ms-transition: color 0.2s ease-out; + -o-transition: color 0.2s ease-out; + transition: color 0.2s ease-out; + padding: 0 5px; + color: #333; } + .rn-carousel-indicator span:before { + content: "\25cf"; } + .rn-carousel-indicator .active { + color: white; } + +/* controls */ +.rn-carousel-control { + -webkit-transition: opacity 0.2s ease-out; + -moz-transition: opacity 0.2s ease-out; + -ms-transition: opacity 0.2s ease-out; + -o-transition: opacity 0.2s ease-out; + transition: opacity 0.2s ease-out; + font-size: 30px; + position: absolute; + top: 50%; + margin-top: -35px; + opacity: 0.75; + cursor: pointer; } + .rn-carousel-control:hover { + opacity: 1; } + .rn-carousel-control.rn-carousel-control-back { + left: 0.5em; } + .rn-carousel-control.rn-carousel-control-back:before { + content: "<"; } + .rn-carousel-control.rn-carousel-control-next { + right: 0.5em; } + .rn-carousel-control.rn-carousel-control-next:before { + content: ">"; } diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js old mode 100644 new mode 100755 index cb37a2d..e39254a --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.1.3 - 2014-01-08 + * @version v0.1.4 - 2014-01-20 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -19,6 +19,30 @@ angular.module('angular-carousel', [ angular.module('angular-carousel') +.directive('rnCarouselControls', [function() { + return { + restrict: 'A', + replace: true, + scope: { + items: '=', + index: '=' + }, + link: function(scope, element, attrs) { + scope.back = function() { + scope.index-- + } + scope.next = function() { + scope.index++ + } + }, + template: '' + }; +}]); +angular.module('angular-carousel') + .directive('rnCarouselIndicators', [function() { return { restrict: 'A', @@ -92,11 +116,6 @@ angular.module('angular-carousel') } return true; }); - if (!isRepeatBased) { - // basic template based carousel - var liChilds = tElement.children(); - slidesCount = tElement.children().length; - } return function(scope, iElement, iAttributes, containerCtrl) { @@ -109,6 +128,7 @@ angular.module('angular-carousel') amplitude, offset = 0, destination, + slidesCount = 0, // javascript based animation easing timestamp; @@ -116,8 +136,8 @@ angular.module('angular-carousel') var carousel = iElement.wrap(""), container = carousel.parent(); - // enable carousel indicator - if (angular.isDefined(iAttributes.rnCarouselIndicator)) { + // if indicator or controls, setup the watch + if(angular.isDefined(iAttributes.rnCarouselIndicator)) { updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; @@ -125,10 +145,17 @@ angular.module('angular-carousel') scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); + var indicator = $compile("")(scope); container.append(indicator); } + // enable carousel controls + if (angular.isDefined(iAttributes.rnCarouselControl)) { + var controls = $compile("")(scope); + container.append(controls); + } + scope.carouselBufferIndex = 0; scope.carouselBufferSize = 5; scope.carouselIndex = 0; @@ -169,6 +196,7 @@ angular.module('angular-carousel') goToSlide(scope.carouselIndex); }); } else { + slidesCount = iElement.children().length; updateContainerWidth(); } diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index 1bbf4ad..74277d7 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden}.rn-carousel-slides{position:relative;white-space:nowrap;overflow:visible;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;position:relative;bottom:20px;height:20px;background-color:#000;background-color:rgba(0,0,0,.6)}.rn-carousel-indicator span{padding:0 5px;color:#333;-webkit-transition:color .2s ease-out;transition:color .2s ease-out}.rn-carousel-indicator .active{color:#fff} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative;padding-bottom:20px}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;position:relative;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:absolute;bottom:0}.rn-carousel-indicator span{-webkit-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-moz-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-ms-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-o-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-moz-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-ms-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-o-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);font-size:20px;position:absolute;top:50%;margin-top:-30px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-back{left:.5em}.rn-carousel-control.rn-carousel-control-back:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 4c9fe83..1a4903e 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.1.3 - 2014-01-08 + * @version v0.1.4 - 2014-01-20 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=0,r=!1;if(j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),!o){{j.children()}q=j.children().length}return function(j,k,l){function n(){for(var a=[],b=0;q>b;b++)a[b]=b;j.carouselIndicatorArray=a}function s(){var a=O.children();return G=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(G)}function t(){P.css("width","100%"),P.css("width",s()+"px")}function u(a){isNaN(a)&&(a=j.carouselIndex*G),N=a;var b=-Math.round(N);b+=j.carouselBufferIndex*G,O[0].style[H]="translate3d("+b+"px, 0, 0)"}function v(){var a,b;K&&(a=Date.now()-M,b=K*Math.exp(-a/g),b>i||-i>b?(u(L-b),requestAnimationFrame(v)):y(L/G))}function w(a){return a>=q?q:0>=a?0:a}function x(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>q-j.carouselBufferSize?q-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function y(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(N=a*G,E(null,null,!0),void 0):(j.carouselIndex=w(a),x(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(r?j.$apply():j.$digest()),u(),void 0)}function z(){return h*G}function A(a){E({x:a.clientX,y:a.clientY},a)}function B(a){var b=a;return 0===j.carouselIndex?b=Math.max(-z(),b):j.carouselIndex===q-1&&(b=Math.min((q-1)*G+z(),b)),b}function C(a,b){return c.bind("mouseup",A),I=!0,J=a.x,K=0,M=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function D(a,b){var c,d;return I&&(c=a.x,d=J-c,(d>2||-2>d)&&(J=c,requestAnimationFrame(function(){u(B(N+d))}))),b.preventDefault(),b.stopPropagation(),!1}function E(a,b,d){c.unbind("mouseup",A),I=!1,L=N;var e=z(),f=j.carouselIndex*G,g=f-L,h=-Math[g>=0?"ceil":"floor"](g/G),i=Math.abs(g)>e;h+j.carouselIndex>=q&&(h=q-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return L=(k+j.carouselIndex)*G,K=L-N,M=Date.now(),d&&(K=N-f),requestAnimationFrame(v),b&&(b.preventDefault(),b.stopPropagation()),!1}function F(){t(),y()}f++;var G,H,I,J,K,L,M,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){y(a,!0)});var Q=e("")(j);P.append(Q)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var R=d(l.rnCarouselIndex);angular.isFunction(R.assign)?(j.$watch("carouselIndex",function(a){R.assign(j.$parent,a)}),j.carouselIndex=R(j),j.$parent.$watch(R,function(a){void 0!==a&&y(a,!0)}),r=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){q=0,angular.isArray(a)?q=a.length:angular.isObject(a)&&(q=Object.keys(a).length),n(),G||t(),y(j.carouselIndex)}):t(),a.bind(O,{start:C,move:D,end:E,cancel:function(a){E({},a)}}),r||y(j.carouselIndex),H="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(H=b,!1):!0});var S=angular.element(b);S.bind("orientationchange",F),S.bind("resize",F),j.$on("$destroy",function(){c.unbind("mouseup",A),S.unbind("orientationchange",F),S.unbind("resize",F)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.back=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=!1;return j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),function(j,k,l){function n(){for(var a=[],b=0;N>b;b++)a[b]=b;j.carouselIndicatorArray=a}function r(){var a=O.children();return F=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(F)}function s(){P.css("width","100%"),P.css("width",r()+"px")}function t(a){isNaN(a)&&(a=j.carouselIndex*F),M=a;var b=-Math.round(M);b+=j.carouselBufferIndex*F,O[0].style[G]="translate3d("+b+"px, 0, 0)"}function u(){var a,b;J&&(a=Date.now()-L,b=J*Math.exp(-a/g),b>i||-i>b?(t(K-b),requestAnimationFrame(u)):x(K/F))}function v(a){return a>=N?N:0>=a?0:a}function w(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>N-j.carouselBufferSize?N-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function x(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(M=a*F,void D(null,null,!0)):(j.carouselIndex=v(a),w(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(q?j.$apply():j.$digest()),void t())}function y(){return h*F}function z(a){D({x:a.clientX,y:a.clientY},a)}function A(a){var b=a;return 0===j.carouselIndex?b=Math.max(-y(),b):j.carouselIndex===N-1&&(b=Math.min((N-1)*F+y(),b)),b}function B(a,b){return c.bind("mouseup",z),H=!0,I=a.x,J=0,L=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function C(a,b){var c,d;return H&&(c=a.x,d=I-c,(d>2||-2>d)&&(I=c,requestAnimationFrame(function(){t(A(M+d))}))),b.preventDefault(),b.stopPropagation(),!1}function D(a,b,d){c.unbind("mouseup",z),H=!1,K=M;var e=y(),f=j.carouselIndex*F,g=f-K,h=-Math[g>=0?"ceil":"floor"](g/F),i=Math.abs(g)>e;h+j.carouselIndex>=N&&(h=N-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return K=(k+j.carouselIndex)*F,J=K-M,L=Date.now(),d&&(J=M-f),requestAnimationFrame(u),b&&(b.preventDefault(),b.stopPropagation()),!1}function E(){s(),x()}f++;var F,G,H,I,J,K,L,M=0,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){x(a,!0)});var Q=e("")(j);P.append(Q)}if(angular.isDefined(l.rnCarouselControl)){var R=e("")(j);P.append(R)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var S=d(l.rnCarouselIndex);angular.isFunction(S.assign)?(j.$watch("carouselIndex",function(a){S.assign(j.$parent,a)}),j.carouselIndex=S(j),j.$parent.$watch(S,function(a){void 0!==a&&x(a,!0)}),q=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){N=0,angular.isArray(a)?N=a.length:angular.isObject(a)&&(N=Object.keys(a).length),n(),F||s(),x(j.carouselIndex)}):(N=k.children().length,s()),a.bind(O,{start:B,move:C,end:D,cancel:function(a){D({},a)}}),q||x(j.carouselIndex),G="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(G=b,!1):!0});var T=angular.element(b);T.bind("orientationchange",E),T.bind("resize",E),j.$on("$destroy",function(){c.unbind("mouseup",z),T.unbind("orientationchange",E),T.unbind("resize",E)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json old mode 100644 new mode 100755 index b6c304a..20a6d71 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "grunt-contrib-jshint": "*", "grunt-contrib-uglify": "*", "grunt-contrib-connect": "*", + "grunt-contrib-sass": "~0.6.0", "grunt-contrib-cssmin": "~0.6.0", "grunt-contrib-watch": "~0.4.4", "grunt-contrib-copy": "~0.5.0", diff --git a/src/css/angular-carousel.css b/src/css/angular-carousel.css deleted file mode 100644 index 71e39ae..0000000 --- a/src/css/angular-carousel.css +++ /dev/null @@ -1,43 +0,0 @@ -/* -generic styles applied to any carousel -use autoprefixer to build the final CSS -*/ -.rn-carousel-container { - overflow: hidden; -} -.rn-carousel-slides { - position: relative; - white-space: nowrap; - overflow: visible; - transform: translate3d(0, 0, 0); - padding: 0; - margin: 0; -} -.rn-carousel-slide { - white-space: normal; - vertical-align:top; - display: inline-block; - width: 100%; - height: 100%; - backface-visibility: hidden; -} - -/* indicator */ - -.rn-carousel-indicator { - width: 100%; - text-align:center; - position:relative; - bottom: 20px; - height:20px; - background-color: rgb(0, 0, 0); - background-color: rgba(0, 0, 0, 0.6); -} -.rn-carousel-indicator span { - padding: 0 5px; - color: #333; - transition: color .2s ease-out; -} -.rn-carousel-indicator .active { - color:white; -} diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss new file mode 100755 index 0000000..0b903fa --- /dev/null +++ b/src/css/angular-carousel.scss @@ -0,0 +1,110 @@ +/* variables */ +$rn-carousel-indicator-height: 20px; +$rn-carousel-control-height: 30px; + +/* mixins */ +@function compact($var-1, $var-2: false, $var-3: false, $var-4: false, $var-5: false, $var-6: false, + $var-7: false, $var-8: false, $var-9: false, $var-10: false) { + $full: $var-1; + $vars: $var-2, $var-3, $var-4, $var-5, + $var-6, $var-7, $var-8, $var-9, $var-10; + @each $var in $vars { + @if $var { $full: $full, $var; } + } + @return $full; +} +@mixin transition($tran-1, $tran-2: false, $tran-3: false, $tran-4: false, $tran-5: false, + $tran-6: false, $tran-7: false, $tran-8: false, $tran-9: false, $tran-10: false) { + $list: compact($tran-1, $tran-2, $tran-3, $tran-4, $tran-5, $tran-6, $tran-7, $tran-8, $tran-9, $tran-10); + -webkit-transition: $list; + -moz-transition: $list; + -ms-transition: $list; + -o-transition: $list; + transition: $list; +} +@mixin translate3d($x:0, $y:0, $z:0) { + -webkit-transform: translate3d($x, $y, $z); + -moz-transform: translate3d($x, $y, $z); + -ms-transform: translate3d($x, $y, $z); + -o-transform: translate3d($x, $y, $z); + transform: translate3d($x, $y, $z); +} + +/* general */ +.rn-carousel-container { + overflow: hidden; + position: relative; + padding-bottom: $rn-carousel-indicator-height; +} +.rn-carousel-slides { + @include translate3d(0,0,0); + position: relative; + white-space: nowrap; + overflow: visible; + padding: 0; + margin: 0; +} +.rn-carousel-slide { + white-space: normal; + vertical-align: top; + display: inline-block; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; +} + +/* indicators */ +.rn-carousel-indicator { + width: 100%; + text-align:center; + position:relative; + height: $rn-carousel-indicator-height; + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.6); + position: absolute; + bottom: 0; + + span { + @include transition(color .2s ease-out); + padding: 0 5px; + color: #333; + &:before { + content: "\25cf"; + } + } + + .active { + color: white; + } +} + +/* controls */ +.rn-carousel-control { + @include transition(opacity 0.2s ease-out); + font-size: $rn-carousel-control-height; + position: absolute; + top: 50%; + margin-top: -$rn-carousel-indicator-height - ($rn-carousel-control-height / 2); + opacity: 0.75; + cursor: pointer; + + &:hover { + opacity: 1; + } + + &.rn-carousel-control-back { + left: 0.5em; + &:before { + content: "<"; + } + } + + &.rn-carousel-control-next { + right: 0.5em; + &:before { + content: ">"; + } + } +} diff --git a/src/directives/rn-carousel-controls.js b/src/directives/rn-carousel-controls.js new file mode 100755 index 0000000..18b177e --- /dev/null +++ b/src/directives/rn-carousel-controls.js @@ -0,0 +1,24 @@ +angular.module('angular-carousel') + +.directive('rnCarouselControls', [function() { + return { + restrict: 'A', + replace: true, + scope: { + items: '=', + index: '=' + }, + link: function(scope, element, attrs) { + scope.back = function() { + scope.index-- + } + scope.next = function() { + scope.index++ + } + }, + template: '' + }; +}]); \ No newline at end of file diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js old mode 100644 new mode 100755 index 453cc8c..597af56 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -77,8 +77,8 @@ var carousel = iElement.wrap(""), container = carousel.parent(); - // enable carousel indicator - if (angular.isDefined(iAttributes.rnCarouselIndicator)) { + // if indicator or controls, setup the watch + if(angular.isDefined(iAttributes.rnCarouselIndicator)) { updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; @@ -86,10 +86,17 @@ scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); + var indicator = $compile("")(scope); container.append(indicator); } + // enable carousel controls + if (angular.isDefined(iAttributes.rnCarouselControl)) { + var controls = $compile("")(scope); + container.append(controls); + } + scope.carouselBufferIndex = 0; scope.carouselBufferSize = 5; scope.carouselIndex = 0; From 31b97e8fed0dc5b514dfb356607aec9c90710879 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 13:53:19 -0600 Subject: [PATCH 021/159] removing the text nodes in favor of CSS content --- src/directives/rn-carousel-controls.js | 4 ++-- src/directives/rn-carousel-indicators.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/directives/rn-carousel-indicators.js diff --git a/src/directives/rn-carousel-controls.js b/src/directives/rn-carousel-controls.js index 18b177e..11de52d 100755 --- a/src/directives/rn-carousel-controls.js +++ b/src/directives/rn-carousel-controls.js @@ -17,8 +17,8 @@ angular.module('angular-carousel') } }, template: '' }; }]); \ No newline at end of file diff --git a/src/directives/rn-carousel-indicators.js b/src/directives/rn-carousel-indicators.js old mode 100644 new mode 100755 index 4916e91..42d5191 --- a/src/directives/rn-carousel-indicators.js +++ b/src/directives/rn-carousel-indicators.js @@ -9,7 +9,7 @@ angular.module('angular-carousel') index: '=' }, template: '' }; }]); From e18e0891908ea0efd165ce20790bd95a502f812d Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 14:03:21 -0600 Subject: [PATCH 022/159] fixing some defunct css --- src/css/angular-carousel.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index 0b903fa..de0925a 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -59,12 +59,12 @@ $rn-carousel-control-height: 30px; .rn-carousel-indicator { width: 100%; text-align:center; - position:relative; height: $rn-carousel-indicator-height; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 0; + cursor: pointer; span { @include transition(color .2s ease-out); From 3f66a20e8eec6a3bc60bde14e1a4ffb00372f680 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 14:18:18 -0600 Subject: [PATCH 023/159] builds and tests --- dist/angular-carousel.css | 4 +-- dist/angular-carousel.js | 6 ++--- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 2 +- test/unit/angular-carousel.js | 49 +++++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 7 deletions(-) mode change 100644 => 100755 test/unit/angular-carousel.js diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index 186f527..1b02e1a 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -32,12 +32,12 @@ .rn-carousel-indicator { width: 100%; text-align: center; - position: relative; height: 20px; background-color: black; background-color: rgba(0, 0, 0, 0.6); position: absolute; - bottom: 0; } + bottom: 0; + cursor: pointer; } .rn-carousel-indicator span { -webkit-transition: color 0.2s ease-out; -moz-transition: color 0.2s ease-out; diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e39254a..e785022 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -36,8 +36,8 @@ angular.module('angular-carousel') } }, template: '' }; }]); @@ -52,7 +52,7 @@ angular.module('angular-carousel') index: '=' }, template: '' }; }]); diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index 74277d7..b84581f 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden;position:relative;padding-bottom:20px}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;position:relative;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:absolute;bottom:0}.rn-carousel-indicator span{-webkit-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-moz-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-ms-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);-o-transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);transition:compact(color .2s ease-out,false,false,false,false,false,false,false,false,false);padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-moz-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-ms-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);-o-transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);transition:compact(opacity .2s ease-out,false,false,false,false,false,false,false,false,false);font-size:20px;position:absolute;top:50%;margin-top:-30px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-back{left:.5em}.rn-carousel-control.rn-carousel-control-back:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative;padding-bottom:20px}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:absolute;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;-moz-transition:color .2s ease-out;-ms-transition:color .2s ease-out;-o-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-ms-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-back{left:.5em}.rn-carousel-control.rn-carousel-control-back:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 1a4903e..2d933b8 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.back=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=!1;return j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),function(j,k,l){function n(){for(var a=[],b=0;N>b;b++)a[b]=b;j.carouselIndicatorArray=a}function r(){var a=O.children();return F=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(F)}function s(){P.css("width","100%"),P.css("width",r()+"px")}function t(a){isNaN(a)&&(a=j.carouselIndex*F),M=a;var b=-Math.round(M);b+=j.carouselBufferIndex*F,O[0].style[G]="translate3d("+b+"px, 0, 0)"}function u(){var a,b;J&&(a=Date.now()-L,b=J*Math.exp(-a/g),b>i||-i>b?(t(K-b),requestAnimationFrame(u)):x(K/F))}function v(a){return a>=N?N:0>=a?0:a}function w(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>N-j.carouselBufferSize?N-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function x(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(M=a*F,void D(null,null,!0)):(j.carouselIndex=v(a),w(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(q?j.$apply():j.$digest()),void t())}function y(){return h*F}function z(a){D({x:a.clientX,y:a.clientY},a)}function A(a){var b=a;return 0===j.carouselIndex?b=Math.max(-y(),b):j.carouselIndex===N-1&&(b=Math.min((N-1)*F+y(),b)),b}function B(a,b){return c.bind("mouseup",z),H=!0,I=a.x,J=0,L=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function C(a,b){var c,d;return H&&(c=a.x,d=I-c,(d>2||-2>d)&&(I=c,requestAnimationFrame(function(){t(A(M+d))}))),b.preventDefault(),b.stopPropagation(),!1}function D(a,b,d){c.unbind("mouseup",z),H=!1,K=M;var e=y(),f=j.carouselIndex*F,g=f-K,h=-Math[g>=0?"ceil":"floor"](g/F),i=Math.abs(g)>e;h+j.carouselIndex>=N&&(h=N-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return K=(k+j.carouselIndex)*F,J=K-M,L=Date.now(),d&&(J=M-f),requestAnimationFrame(u),b&&(b.preventDefault(),b.stopPropagation()),!1}function E(){s(),x()}f++;var F,G,H,I,J,K,L,M=0,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){x(a,!0)});var Q=e("")(j);P.append(Q)}if(angular.isDefined(l.rnCarouselControl)){var R=e("")(j);P.append(R)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var S=d(l.rnCarouselIndex);angular.isFunction(S.assign)?(j.$watch("carouselIndex",function(a){S.assign(j.$parent,a)}),j.carouselIndex=S(j),j.$parent.$watch(S,function(a){void 0!==a&&x(a,!0)}),q=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){N=0,angular.isArray(a)?N=a.length:angular.isObject(a)&&(N=Object.keys(a).length),n(),F||s(),x(j.carouselIndex)}):(N=k.children().length,s()),a.bind(O,{start:B,move:C,end:D,cancel:function(a){D({},a)}}),q||x(j.carouselIndex),G="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(G=b,!1):!0});var T=angular.element(b);T.bind("orientationchange",E),T.bind("resize",E),j.$on("$destroy",function(){c.unbind("mouseup",z),T.unbind("orientationchange",E),T.unbind("resize",E)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.back=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=!1;return j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),function(j,k,l){function n(){for(var a=[],b=0;N>b;b++)a[b]=b;j.carouselIndicatorArray=a}function r(){var a=O.children();return F=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(F)}function s(){P.css("width","100%"),P.css("width",r()+"px")}function t(a){isNaN(a)&&(a=j.carouselIndex*F),M=a;var b=-Math.round(M);b+=j.carouselBufferIndex*F,O[0].style[G]="translate3d("+b+"px, 0, 0)"}function u(){var a,b;J&&(a=Date.now()-L,b=J*Math.exp(-a/g),b>i||-i>b?(t(K-b),requestAnimationFrame(u)):x(K/F))}function v(a){return a>=N?N:0>=a?0:a}function w(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>N-j.carouselBufferSize?N-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function x(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(M=a*F,void D(null,null,!0)):(j.carouselIndex=v(a),w(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(q?j.$apply():j.$digest()),void t())}function y(){return h*F}function z(a){D({x:a.clientX,y:a.clientY},a)}function A(a){var b=a;return 0===j.carouselIndex?b=Math.max(-y(),b):j.carouselIndex===N-1&&(b=Math.min((N-1)*F+y(),b)),b}function B(a,b){return c.bind("mouseup",z),H=!0,I=a.x,J=0,L=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function C(a,b){var c,d;return H&&(c=a.x,d=I-c,(d>2||-2>d)&&(I=c,requestAnimationFrame(function(){t(A(M+d))}))),b.preventDefault(),b.stopPropagation(),!1}function D(a,b,d){c.unbind("mouseup",z),H=!1,K=M;var e=y(),f=j.carouselIndex*F,g=f-K,h=-Math[g>=0?"ceil":"floor"](g/F),i=Math.abs(g)>e;h+j.carouselIndex>=N&&(h=N-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return K=(k+j.carouselIndex)*F,J=K-M,L=Date.now(),d&&(J=M-f),requestAnimationFrame(u),b&&(b.preventDefault(),b.stopPropagation()),!1}function E(){s(),x()}f++;var F,G,H,I,J,K,L,M=0,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){x(a,!0)});var Q=e("")(j);P.append(Q)}if(angular.isDefined(l.rnCarouselControl)){var R=e("")(j);P.append(R)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var S=d(l.rnCarouselIndex);angular.isFunction(S.assign)?(j.$watch("carouselIndex",function(a){S.assign(j.$parent,a)}),j.carouselIndex=S(j),j.$parent.$watch(S,function(a){void 0!==a&&x(a,!0)}),q=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){N=0,angular.isArray(a)?N=a.length:angular.isObject(a)&&(N=Object.keys(a).length),n(),F||s(),x(j.carouselIndex)}):(N=k.children().length,s()),a.bind(O,{start:B,move:C,end:D,cancel:function(a){D({},a)}}),q||x(j.carouselIndex),G="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(G=b,!1):!0});var T=angular.element(b);T.bind("orientationchange",E),T.bind("resize",E),j.$on("$destroy",function(){c.unbind("mouseup",z),T.unbind("orientationchange",E),T.unbind("resize",E)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/test/unit/angular-carousel.js b/test/unit/angular-carousel.js old mode 100644 new mode 100755 index 0606bf5..669b251 --- a/test/unit/angular-carousel.js +++ b/test/unit/angular-carousel.js @@ -37,6 +37,7 @@ describe('carousel', function () { var options = { useIndex: false, useIndicator: false, + useControl: false, useBuffer: false, nbItems: 25, useWatch: false @@ -56,6 +57,7 @@ describe('carousel', function () { } var tpl = '
          Date: Mon, 20 Jan 2014 14:37:56 -0600 Subject: [PATCH 024/159] adding tests --- test/unit/angular-carousel.js | 63 ++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/test/unit/angular-carousel.js b/test/unit/angular-carousel.js index 669b251..faea0e9 100755 --- a/test/unit/angular-carousel.js +++ b/test/unit/angular-carousel.js @@ -5,14 +5,14 @@ describe('carousel', function () { var scope, $compile, $sandbox; -/* + //$('body').append(""); - $('body').append(""); -*/ + "-o-transition: none;transition: none;}");*/ + //console.log(document.location); beforeEach( module('angular-carousel') @@ -75,16 +75,16 @@ describe('carousel', function () { return curMatrix; } function validCSStransform(elm) { - var expectedPosition = (elm.outerWidth() * elm.scope().carouselCollection.index * -1), + var expectedPosition = (elm.offsetWidth * elm.scope().carouselCollection.index * -1), expectedMatrix = 'matrix(1, 0, 0, 1, ' + expectedPosition + ', 0)', curMatrix = getElmTransform(elm); expect(curMatrix).toBe(expectedMatrix); } - +/* it('should load test', function() { expect(1).toBe(1); }); -/* + describe('directive', function () { it('should add a wrapper div around the ul/li', function () { var elm = compileTpl(); @@ -100,7 +100,7 @@ describe('carousel', function () { }); it('generated container outerWidth should match the ul outerWidth', function () { var elm = compileTpl(); - expect(elm.parent().outerWidth()).toBe(elm.outerWidth()); + expect(elm.parent()[0].offsetWidth).toBe(elm[0].offsetWidth); }); }); @@ -226,6 +226,29 @@ describe('carousel', function () { }); }); + describe('directive with no index defined', function () { + it('should add a wrapper div around the ul/li', function () { + var elm = compileTpl({useIndex:false}); + expect(elm.parent().hasClass('rn-carousel-container')).toBe(true); + }); + it('should add a class to the ul', function () { + var elm = compileTpl({useIndex:false}); + expect(elm.hasClass('rn-carousel-slides')).toBe(true); + }); + it('should have enough slides', function () { + var elm = compileTpl({useIndex:false}); + expect(elm.find('li').length).toBe(scope.items.length); + }); + it('generated container outerWidth should match the ul outerWidth', function () { + var elm = compileTpl({useIndex:false}); + expect(elm.parent().outerWidth()).toBe(elm.outerWidth()); + }); + it('the index attribute should be used to position the first visible slide', function () { + var elm = compileTpl({useIndex:false}); + validCSStransform(elm); + }); + }); + describe('buffered carousel', function () { it('should minimize the DOM', function () { var elm = compileTpl({useBuffer: true}); @@ -595,29 +618,7 @@ describe('carousel', function () { // }); // }); //}); - */ - describe('directive with no index defined', function () { - it('should add a wrapper div around the ul/li', function () { - var elm = compileTpl({useIndex:false}); - expect(elm.parent().hasClass('rn-carousel-container')).toBe(true); - }); - it('should add a class to the ul', function () { - var elm = compileTpl({useIndex:false}); - expect(elm.hasClass('rn-carousel-slides')).toBe(true); - }); - it('should have enough slides', function () { - var elm = compileTpl({useIndex:false}); - expect(elm.find('li').length).toBe(scope.items.length); - }); - it('generated container outerWidth should match the ul outerWidth', function () { - var elm = compileTpl({useIndex:false}); - expect(elm.parent().outerWidth()).toBe(elm.outerWidth()); - }); - it('the index attribute should be used to position the first visible slide', function () { - var elm = compileTpl({useIndex:false}); - validCSStransform(elm); - }); - }); + }); From 7dce74e8bb8f213711939ad5a96d55021a49fb84 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 14:44:42 -0600 Subject: [PATCH 025/159] we need to setup the watch on carouselIndex and indicatorIndex for both controls and indicators --- dist/angular-carousel.js | 6 +++++- dist/angular-carousel.min.js | 2 +- src/directives/rn-carousel.js | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e785022..06f5ae3 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -137,7 +137,7 @@ angular.module('angular-carousel') container = carousel.parent(); // if indicator or controls, setup the watch - if(angular.isDefined(iAttributes.rnCarouselIndicator)) { + if (angular.isDefined(iAttributes.rnCarouselIndicator) || angular.isDefined(iAttributes.rnCarouselControl)) { updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; @@ -146,6 +146,10 @@ angular.module('angular-carousel') goToSlide(newValue, true); }); + } + + // enable carousel indicator + if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); container.append(indicator); } diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 2d933b8..cd79d5a 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.back=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=!1;return j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),function(j,k,l){function n(){for(var a=[],b=0;N>b;b++)a[b]=b;j.carouselIndicatorArray=a}function r(){var a=O.children();return F=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(F)}function s(){P.css("width","100%"),P.css("width",r()+"px")}function t(a){isNaN(a)&&(a=j.carouselIndex*F),M=a;var b=-Math.round(M);b+=j.carouselBufferIndex*F,O[0].style[G]="translate3d("+b+"px, 0, 0)"}function u(){var a,b;J&&(a=Date.now()-L,b=J*Math.exp(-a/g),b>i||-i>b?(t(K-b),requestAnimationFrame(u)):x(K/F))}function v(a){return a>=N?N:0>=a?0:a}function w(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>N-j.carouselBufferSize?N-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function x(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(M=a*F,void D(null,null,!0)):(j.carouselIndex=v(a),w(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(q?j.$apply():j.$digest()),void t())}function y(){return h*F}function z(a){D({x:a.clientX,y:a.clientY},a)}function A(a){var b=a;return 0===j.carouselIndex?b=Math.max(-y(),b):j.carouselIndex===N-1&&(b=Math.min((N-1)*F+y(),b)),b}function B(a,b){return c.bind("mouseup",z),H=!0,I=a.x,J=0,L=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function C(a,b){var c,d;return H&&(c=a.x,d=I-c,(d>2||-2>d)&&(I=c,requestAnimationFrame(function(){t(A(M+d))}))),b.preventDefault(),b.stopPropagation(),!1}function D(a,b,d){c.unbind("mouseup",z),H=!1,K=M;var e=y(),f=j.carouselIndex*F,g=f-K,h=-Math[g>=0?"ceil":"floor"](g/F),i=Math.abs(g)>e;h+j.carouselIndex>=N&&(h=N-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return K=(k+j.carouselIndex)*F,J=K-M,L=Date.now(),d&&(J=M-f),requestAnimationFrame(u),b&&(b.preventDefault(),b.stopPropagation()),!1}function E(){s(),x()}f++;var F,G,H,I,J,K,L,M=0,N=0,O=k.wrap(""),P=O.parent();if(angular.isDefined(l.rnCarouselIndicator)){n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){x(a,!0)});var Q=e("")(j);P.append(Q)}if(angular.isDefined(l.rnCarouselControl)){var R=e("")(j);P.append(R)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var S=d(l.rnCarouselIndex);angular.isFunction(S.assign)?(j.$watch("carouselIndex",function(a){S.assign(j.$parent,a)}),j.carouselIndex=S(j),j.$parent.$watch(S,function(a){void 0!==a&&x(a,!0)}),q=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){N=0,angular.isArray(a)?N=a.length:angular.isObject(a)&&(N=Object.keys(a).length),n(),F||s(),x(j.carouselIndex)}):(N=k.children().length,s()),a.bind(O,{start:B,move:C,end:D,cancel:function(a){D({},a)}}),q||x(j.carouselIndex),G="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(G=b,!1):!0});var T=angular.element(b);T.bind("orientationchange",E),T.bind("resize",E),j.$on("$destroy",function(){c.unbind("mouseup",z),T.unbind("orientationchange",E),T.unbind("resize",E)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.back=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile",function(a,b,c,d,e){var f=0,g=75,h=.05,i=3;return{restrict:"A",scope:!0,compile:function(j,k){var l,m,n=j.children()[0].attributes,o=!1,p=!1,q=!1;return j.addClass("rn-carousel-slides"),j.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=n[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(l=c[1],m=c[2],l)return angular.isDefined(k.rnCarouselBuffered)&&(p=!0,b.value=l+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),o=!0,!1}return!0}),function(j,k,l){function n(){for(var a=[],b=0;N>b;b++)a[b]=b;j.carouselIndicatorArray=a}function r(){var a=O.children();return F=0===a.length?O[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width,Math.floor(F)}function s(){P.css("width","100%"),P.css("width",r()+"px")}function t(a){isNaN(a)&&(a=j.carouselIndex*F),M=a;var b=-Math.round(M);b+=j.carouselBufferIndex*F,O[0].style[G]="translate3d("+b+"px, 0, 0)"}function u(){var a,b;J&&(a=Date.now()-L,b=J*Math.exp(-a/g),b>i||-i>b?(t(K-b),requestAnimationFrame(u)):x(K/F))}function v(a){return a>=N?N:0>=a?0:a}function w(){var a=0,b=(j.carouselBufferSize-1)/2;p&&(a=j.carouselIndex<=b?0:j.carouselIndex>N-j.carouselBufferSize?N-j.carouselBufferSize:j.carouselIndex-b),j.carouselBufferIndex=a}function x(a,b){return isNaN(a)&&(a=j.carouselIndex),b?(M=a*F,void D(null,null,!0)):(j.carouselIndex=v(a),w(),"$apply"!==j.$$phase&&"$digest"!==j.$$phase&&(q?j.$apply():j.$digest()),void t())}function y(){return h*F}function z(a){D({x:a.clientX,y:a.clientY},a)}function A(a){var b=a;return 0===j.carouselIndex?b=Math.max(-y(),b):j.carouselIndex===N-1&&(b=Math.min((N-1)*F+y(),b)),b}function B(a,b){return c.bind("mouseup",z),H=!0,I=a.x,J=0,L=Date.now(),b.preventDefault(),b.stopPropagation(),!1}function C(a,b){var c,d;return H&&(c=a.x,d=I-c,(d>2||-2>d)&&(I=c,requestAnimationFrame(function(){t(A(M+d))}))),b.preventDefault(),b.stopPropagation(),!1}function D(a,b,d){c.unbind("mouseup",z),H=!1,K=M;var e=y(),f=j.carouselIndex*F,g=f-K,h=-Math[g>=0?"ceil":"floor"](g/F),i=Math.abs(g)>e;h+j.carouselIndex>=N&&(h=N-1-j.carouselIndex),h+j.carouselIndex<0&&(h=-j.carouselIndex);var k=i?h:0;return K=(k+j.carouselIndex)*F,J=K-M,L=Date.now(),d&&(J=M-f),requestAnimationFrame(u),b&&(b.preventDefault(),b.stopPropagation()),!1}function E(){s(),x()}f++;var F,G,H,I,J,K,L,M=0,N=0,O=k.wrap(""),P=O.parent();if((angular.isDefined(l.rnCarouselIndicator)||angular.isDefined(l.rnCarouselControl))&&(n(),j.$watch("carouselIndex",function(a){j.indicatorIndex=a}),j.$watch("indicatorIndex",function(a){x(a,!0)})),angular.isDefined(l.rnCarouselIndicator)){var Q=e("")(j);P.append(Q)}if(angular.isDefined(l.rnCarouselControl)){var R=e("")(j);P.append(R)}if(j.carouselBufferIndex=0,j.carouselBufferSize=5,j.carouselIndex=0,l.rnCarouselIndex){var S=d(l.rnCarouselIndex);angular.isFunction(S.assign)?(j.$watch("carouselIndex",function(a){S.assign(j.$parent,a)}),j.carouselIndex=S(j),j.$parent.$watch(S,function(a){void 0!==a&&x(a,!0)}),q=!0):isNaN(l.rnCarouselIndex)||(j.carouselIndex=parseInt(l.rnCarouselIndex,10))}o?j.$watchCollection(m,function(a){N=0,angular.isArray(a)?N=a.length:angular.isObject(a)&&(N=Object.keys(a).length),n(),F||s(),x(j.carouselIndex)}):(N=k.children().length,s()),a.bind(O,{start:B,move:C,end:D,cancel:function(a){D({},a)}}),q||x(j.carouselIndex),G="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(G=b,!1):!0});var T=angular.element(b);T.bind("orientationchange",E),T.bind("resize",E),j.$on("$destroy",function(){c.unbind("mouseup",z),T.unbind("orientationchange",E),T.unbind("resize",E)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 597af56..dec2846 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -78,7 +78,7 @@ container = carousel.parent(); // if indicator or controls, setup the watch - if(angular.isDefined(iAttributes.rnCarouselIndicator)) { + if (angular.isDefined(iAttributes.rnCarouselIndicator) || angular.isDefined(iAttributes.rnCarouselControl)) { updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; @@ -87,6 +87,10 @@ goToSlide(newValue, true); }); + } + + // enable carousel indicator + if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); container.append(indicator); } From df4356067eef391d031d33f761272e1a45e709ce Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Mon, 20 Jan 2014 17:49:26 -0600 Subject: [PATCH 026/159] letting autoprefixer do its thing --- Gruntfile.js | 11 ++++++----- dist/angular-carousel.css | 13 ++----------- dist/angular-carousel.min.css | 2 +- src/css/angular-carousel.scss | 36 +++-------------------------------- 4 files changed, 12 insertions(+), 50 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 88aa0f9..a5396f8 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -36,10 +36,10 @@ module.exports = function(grunt) { }, autoprefixer: { source: { - options: { - //browsers: ['last 2 version', '> 1%', 'android', 'chrome', 'firefox'] - }, - src: '<%= dirs.src %>/css/<%= pkg.name %>.css', + //options: { + //browsers: ['last 2 version'] + //}, + src: '<%= dirs.dest %>/<%= pkg.name %>.css', dest: '<%= dirs.dest %>/<%= pkg.name %>.css' } }, @@ -52,6 +52,7 @@ module.exports = function(grunt) { dest: '<%= dirs.dest %>/<%= pkg.name %>.js' } }, + sass: { dist: { files: [{ @@ -142,7 +143,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-karma'); // Build task. - grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'autoprefixer', 'sass', 'cssmin']); + grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'sass', 'autoprefixer', 'cssmin']); // Default task. grunt.registerTask('default', ['build', 'connect', 'karma:unit', 'watch']); diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index 1b02e1a..21ece43 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -1,5 +1,4 @@ /* variables */ -/* mixins */ /* general */ .rn-carousel-container { overflow: hidden; @@ -8,9 +7,7 @@ .rn-carousel-slides { -webkit-transform: translate3d(0, 0, 0); - -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); position: relative; white-space: nowrap; @@ -39,11 +36,8 @@ bottom: 0; cursor: pointer; } .rn-carousel-indicator span { - -webkit-transition: color 0.2s ease-out; - -moz-transition: color 0.2s ease-out; - -ms-transition: color 0.2s ease-out; - -o-transition: color 0.2s ease-out; - transition: color 0.2s ease-out; + -webkit-transition: color .2s ease-out; + transition: color .2s ease-out; padding: 0 5px; color: #333; } .rn-carousel-indicator span:before { @@ -54,9 +48,6 @@ /* controls */ .rn-carousel-control { -webkit-transition: opacity 0.2s ease-out; - -moz-transition: opacity 0.2s ease-out; - -ms-transition: opacity 0.2s ease-out; - -o-transition: opacity 0.2s ease-out; transition: opacity 0.2s ease-out; font-size: 30px; position: absolute; diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index b84581f..bdb25a3 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden;position:relative;padding-bottom:20px}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:absolute;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;-moz-transition:color .2s ease-out;-ms-transition:color .2s ease-out;-o-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-ms-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-back{left:.5em}.rn-carousel-control.rn-carousel-control-back:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative;padding-bottom:20px}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:absolute;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-back{left:.5em}.rn-carousel-control.rn-carousel-control-back:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index de0925a..a52503a 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -2,34 +2,6 @@ $rn-carousel-indicator-height: 20px; $rn-carousel-control-height: 30px; -/* mixins */ -@function compact($var-1, $var-2: false, $var-3: false, $var-4: false, $var-5: false, $var-6: false, - $var-7: false, $var-8: false, $var-9: false, $var-10: false) { - $full: $var-1; - $vars: $var-2, $var-3, $var-4, $var-5, - $var-6, $var-7, $var-8, $var-9, $var-10; - @each $var in $vars { - @if $var { $full: $full, $var; } - } - @return $full; -} -@mixin transition($tran-1, $tran-2: false, $tran-3: false, $tran-4: false, $tran-5: false, - $tran-6: false, $tran-7: false, $tran-8: false, $tran-9: false, $tran-10: false) { - $list: compact($tran-1, $tran-2, $tran-3, $tran-4, $tran-5, $tran-6, $tran-7, $tran-8, $tran-9, $tran-10); - -webkit-transition: $list; - -moz-transition: $list; - -ms-transition: $list; - -o-transition: $list; - transition: $list; -} -@mixin translate3d($x:0, $y:0, $z:0) { - -webkit-transform: translate3d($x, $y, $z); - -moz-transform: translate3d($x, $y, $z); - -ms-transform: translate3d($x, $y, $z); - -o-transform: translate3d($x, $y, $z); - transform: translate3d($x, $y, $z); -} - /* general */ .rn-carousel-container { overflow: hidden; @@ -37,7 +9,7 @@ $rn-carousel-control-height: 30px; padding-bottom: $rn-carousel-indicator-height; } .rn-carousel-slides { - @include translate3d(0,0,0); + transform: translate3d(0,0,0); position: relative; white-space: nowrap; overflow: visible; @@ -50,8 +22,6 @@ $rn-carousel-control-height: 30px; display: inline-block; width: 100%; height: 100%; - -webkit-backface-visibility: hidden; - -ms-backface-visibility: hidden; backface-visibility: hidden; } @@ -67,7 +37,7 @@ $rn-carousel-control-height: 30px; cursor: pointer; span { - @include transition(color .2s ease-out); + transition: color .2s ease-out; padding: 0 5px; color: #333; &:before { @@ -82,7 +52,7 @@ $rn-carousel-control-height: 30px; /* controls */ .rn-carousel-control { - @include transition(opacity 0.2s ease-out); + transition: opacity 0.2s ease-out; font-size: $rn-carousel-control-height; position: absolute; top: 50%; From 9d53957f4b1cb95d755c55e76aec5c370af58684 Mon Sep 17 00:00:00 2001 From: Pascal Garber Date: Sun, 19 Jan 2014 00:04:10 +0100 Subject: [PATCH 027/159] feature: add rn-carousel-swipe boolean attribute - controls the carousel swipe-ability dynamically --- index.html | 15 ++++++++++++--- src/directives/rn-carousel.js | 23 ++++++++++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index e786753..5bde618 100644 --- a/index.html +++ b/index.html @@ -70,7 +70,7 @@

          Standard carousel with thumbs navigation

          buffered ngRepeat carousel with custom controls

          Custom controls demo, just update the rn-carousel-index index binding
          -
            +
            • {{ slide.label }} / {{ slides4.length }} @@ -85,6 +85,7 @@

              buffered ngRepeat carousel with custom controls

              {{ slideIndex + 1 }} / {{ slides4.length }} +

              object-based ngRepeat carousel with indicators

              @@ -112,9 +113,13 @@

              Other demos



            - - + + + ``` - - 2. Add a dependency to the `angular-carousel` module in your application. + - Add a dependency to the `angular-carousel` module in your application. ```js angular.module('MyApp', ['angular-carousel']); ``` - 3. Add a `rn-carousel` attribute to your `
              ` block and your `
            • `'s become magically swipable ;) + - Add a `rn-carousel` attribute to your `
                ` block and your `
              • `'s become magically swipable ;) ```html
                • @@ -35,7 +34,7 @@ angular.module('MyApp', ['angular-carousel']);
                ``` - 4. You can also use `rn-carousel` without ng-repeat ;) + - You can also use `rn-carousel` without ng-repeat ;) ```html
                • slide #1
                • From ba414796a5c392acf6b632d6e3fc3427d6a85371 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 15 May 2014 09:47:39 -0500 Subject: [PATCH 056/159] added conditional statement to prev/next fn Prevent carousel controls from navigating past valid item range which would "break" navigation in the other direction. --- src/directives/rn-carousel-controls.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/directives/rn-carousel-controls.js b/src/directives/rn-carousel-controls.js index 8322cd3..6c906de 100755 --- a/src/directives/rn-carousel-controls.js +++ b/src/directives/rn-carousel-controls.js @@ -10,10 +10,10 @@ angular.module('angular-carousel') }, link: function(scope, element, attrs) { scope.prev = function() { - scope.index--; + if (scope.index > 0) scope.index--; }; scope.next = function() { - scope.index++; + if (scope.index < scope.items.length-1) scope.index++; }; }, template: '


                + +

                Autoplay slider

                +
                + By adding rn-carousel-auto-slide with an integer value will make the slider automatically change the visible slide after n seconds +
                + By adding rn-carousel-pause-on-hover="true" the slide will pause on mouse hover and start on mouse leave +
                +
                  +
                • + This is a standard template +
                  slide #1
                  +
                • +
                • + Here's sophie :
                  + +
                • +
                • + A friend of mine :
                  + +
                • +
                • + And to finish : + +
                • +
                +

                diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js new file mode 100644 index 0000000..4ad501f --- /dev/null +++ b/src/directives/rn-carousel-auto-slide.js @@ -0,0 +1,44 @@ +angular.module('angular-carousel') + +.directive('rnCarouselAutoSlide', ['$interval', function($interval) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), + timer = isPaused = increment = false; + + stopAutoplay = function () { + if (angular.isDefined(timer)) { + $interval.cancel(timer); + } + timer = undefined; + }; + + increment = function () { + if(!isPaused){ + if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { + scope.indicatorIndex++; + } else { + scope.indicatorIndex = 0; + } + } + + }; + + timer = $interval(increment, delay); + console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); + if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ + element.on('mouseenter', function(){ + stopAutoplay(); + }); + + element.on('mouseleave', function(){ + timer = $interval(increment, delay); + }); + } + + scope.$on('$destroy', stopAutoplay); + + } + }; +}]); \ No newline at end of file From 4a48df6f79d16983eefbe351ada9adc5139f01e6 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Tue, 8 Jul 2014 15:18:11 +0300 Subject: [PATCH 062/159] removing console log --- dist/angular-carousel.js | 1 - dist/angular-carousel.min.js | 2 +- src/directives/rn-carousel-auto-slide.js | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e747986..eb5bff6 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -45,7 +45,6 @@ angular.module('angular-carousel') }; timer = $interval(increment, delay); - console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index e8372d3..c5013a3 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index 4ad501f..eaf4500 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -26,7 +26,6 @@ angular.module('angular-carousel') }; timer = $interval(increment, delay); - console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); From 585056e80151b002fe3c88ac28c3413b8664b7cc Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 14 Jul 2014 12:33:52 +0300 Subject: [PATCH 063/159] adding .idea to gitignore for ppl who use webstorm --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8260c04..90b4e22 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules bower_components coverage +.idea \ No newline at end of file From 90e26a607a65bbda3eb3cf888454521bafa5e27f Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 14 Jul 2014 13:41:19 +0300 Subject: [PATCH 064/159] removing dependecy to indicator and adding support for carousel controlls --- dist/angular-carousel.js | 38 ++++++++++++++++-------- dist/angular-carousel.min.js | 4 +-- index.html | 2 +- src/directives/rn-carousel-auto-slide.js | 31 ++++++++++++------- src/directives/rn-carousel.js | 5 +++- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index eb5bff6..c030cdb 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-08 + * @version v0.2.3 - 2014-07-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -19,39 +19,48 @@ angular.module('angular-carousel', [ angular.module('angular-carousel') -.directive('rnCarouselAutoSlide', ['$interval', function($interval) { +.directive('rnCarouselAutoSlide', ['$timeout', function($timeout) { return { restrict: 'A', link: function (scope, element, attrs) { var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), - timer = isPaused = increment = false; + timer = increment = false, slidesCount = element.children().length; + if(!scope.carouselExposedIndex){ + scope.carouselExposedIndex = 0; + } stopAutoplay = function () { if (angular.isDefined(timer)) { - $interval.cancel(timer); + $timeout.cancel(timer); } timer = undefined; }; increment = function () { - if(!isPaused){ - if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { - scope.indicatorIndex++; - } else { - scope.indicatorIndex = 0; - } + if (scope.carouselExposedIndex < slidesCount - 1) { + scope.carouselExposedIndex = scope.carouselExposedIndex + 1; + } else { + scope.carouselExposedIndex = 0; } + }; + restartTimer = function (){ + stopAutoplay(); + timer = $timeout(increment, delay); }; - timer = $interval(increment, delay); + scope.$watch('carouselIndex', function(){ + restartTimer(); + }); + + restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); }); element.on('mouseleave', function(){ - timer = $interval(increment, delay); + restartTimer(); }); } @@ -199,13 +208,16 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; + scope.carouselExposedIndex = newValue; }); scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); - } + scope.$watch('carouselExposedIndex', function(newValue) { + goToSlide(newValue, true); + }); // enable carousel indicator if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index c5013a3..a824116 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-08 + * @version v0.2.3 - 2014-07-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index fb0c716..c13f388 100644 --- a/index.html +++ b/index.html @@ -129,7 +129,7 @@

                Autoplay slider


                By adding rn-carousel-pause-on-hover="true" the slide will pause on mouse hover and start on mouse leave -
                  +
                  • This is a standard template
                    slide #1
                    diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index eaf4500..7445eb2 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -1,38 +1,47 @@ angular.module('angular-carousel') -.directive('rnCarouselAutoSlide', ['$interval', function($interval) { +.directive('rnCarouselAutoSlide', ['$timeout', function($timeout) { return { restrict: 'A', link: function (scope, element, attrs) { var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), - timer = isPaused = increment = false; + timer = increment = false, slidesCount = element.children().length; + if(!scope.carouselExposedIndex){ + scope.carouselExposedIndex = 0; + } stopAutoplay = function () { if (angular.isDefined(timer)) { - $interval.cancel(timer); + $timeout.cancel(timer); } timer = undefined; }; increment = function () { - if(!isPaused){ - if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { - scope.indicatorIndex++; - } else { - scope.indicatorIndex = 0; - } + if (scope.carouselExposedIndex < slidesCount - 1) { + scope.carouselExposedIndex = scope.carouselExposedIndex + 1; + } else { + scope.carouselExposedIndex = 0; } + }; + restartTimer = function (){ + stopAutoplay(); + timer = $timeout(increment, delay); }; - timer = $interval(increment, delay); + scope.$watch('carouselIndex', function(){ + restartTimer(); + }); + + restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); }); element.on('mouseleave', function(){ - timer = $interval(increment, delay); + restartTimer(); }); } diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 5bf347b..9365a6c 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -85,13 +85,16 @@ updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; + scope.carouselExposedIndex = newValue; }); scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); - } + scope.$watch('carouselExposedIndex', function(newValue) { + goToSlide(newValue, true); + }); // enable carousel indicator if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); From 878aa9603fa52b378870cfb793307a86838656b3 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 21 Jul 2014 17:46:17 +0300 Subject: [PATCH 065/159] removeing events on scope destroy --- src/directives/rn-carousel-auto-slide.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index 7445eb2..6773b6b 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -36,16 +36,17 @@ angular.module('angular-carousel') restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ - element.on('mouseenter', function(){ - stopAutoplay(); - }); + element.on('mouseenter', stopAutoplay); - element.on('mouseleave', function(){ - restartTimer(); - }); + element.on('mouseleave', restartTimer); } - scope.$on('$destroy', stopAutoplay); + scope.$on('$destroy', function(){ + stopAutoplay(); + element.off('mouseenter', stopAutoplay); + element.off('mouseleave', restartTimer); + }); + } }; From bbe4deb0abf5e1d4e4752b200493c731509bd367 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 21 Jul 2014 17:53:22 +0300 Subject: [PATCH 066/159] moving the demo before ``Other demos`` --- dist/angular-carousel.js | 17 +++++++++-------- dist/angular-carousel.min.js | 4 ++-- index.html | 12 ++++++------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index c030cdb..5fd365e 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-14 + * @version v0.2.3 - 2014-07-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -55,16 +55,17 @@ angular.module('angular-carousel') restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ - element.on('mouseenter', function(){ - stopAutoplay(); - }); + element.on('mouseenter', stopAutoplay); - element.on('mouseleave', function(){ - restartTimer(); - }); + element.on('mouseleave', restartTimer); } - scope.$on('$destroy', stopAutoplay); + scope.$on('$destroy', function(){ + stopAutoplay(); + element.off('mouseenter', stopAutoplay); + element.off('mouseleave', restartTimer); + }); + } }; diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index a824116..5d8559e 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-14 + * @version v0.2.3 - 2014-07-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index c13f388..235a15f 100644 --- a/index.html +++ b/index.html @@ -117,12 +117,6 @@

                    togglable carousel via ng-if

                  -

                  Other demos

                  - -

                  -

                  Autoplay slider

                  By adding rn-carousel-auto-slide with an integer value will make the slider automatically change the visible slide after n seconds @@ -148,6 +142,12 @@

                  Autoplay slider



                +

                Other demos

                + +

                + From a80bdb8b74111b2a834cec917eee18a2d0fafb5e Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Mon, 21 Jul 2014 23:30:46 +0200 Subject: [PATCH 067/159] chore(readme): add auto-slide informations --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5acba04..1a4569d 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ angular.module('MyApp', ['angular-carousel']); - `rn-carousel-buffered` boolean value to enable the carousel buffering, good to minimize the DOM, defaults to 5 slides. (works only with arrays) - `rn-carousel-swipe` boolean value to enable/disable swiping (default true) - `rn-carousel-control` boolean value to enable builtin prev/next buttons (you can override by CSS) - + - `rn-carousel-auto-slide` integer value will make the slider automatically change the visible slide after given seconds + - `rn-carousel-pause-on-hover="true"` prevent auto-slide on hover + ## Todo : - see the [TODO file](./TODO) From 873e4a6d84e0e86edd8a012b0956464ff4fcd66e Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 24 Jul 2014 23:32:21 +0200 Subject: [PATCH 068/159] fix(indicator): prevent transition conflict with ngAnimate --- dist/angular-carousel.css | 3 +++ dist/angular-carousel.min.css | 2 +- src/css/angular-carousel.scss | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index d8c85fb..bbb22da 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -52,6 +52,9 @@ color: #333; } .rn-carousel-indicator span:before { content: "\25cf"; } + .rn-carousel-indicator span.ng-leave { + -webkit-transition: none !important; + transition: none !important; } .rn-carousel-indicator .active { color: white; } diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index bbbbae8..8a9d7dd 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden;position:relative}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator span.ng-leave{-webkit-transition:none!important;transition:none!important}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index c421131..849abef 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -53,6 +53,10 @@ $rn-carousel-control-height: 30px; &:before { content: "\25cf"; } + &.ng-leave { + // see https://github.com/revolunet/angular-carousel/issues/179 + transition: none !important; + } } .active { From 54e503a1e6232a73c9a743607c7ef5ea1cb543df Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 17 Jun 2014 17:50:59 +0200 Subject: [PATCH 069/159] Update README.md using `background-image` the angular way: https://docs.angularjs.org/api/ng/directive/ngStyle --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed10c53..5acba04 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ angular.module('MyApp', ['angular-carousel']); - Add a `rn-carousel` attribute to your `
                  ` block and your `
                • `'s become magically swipable ;) ```html
                    -
                  • +
                  • {{ image }}
                  From 62505b43b6114e15628f7d6ade6f7934afa80d55 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Tue, 8 Jul 2014 15:10:29 +0300 Subject: [PATCH 070/159] adding support for automatic slider and pause on hover --- dist/angular-carousel.js | 73 ++++++++++++++++++++---- dist/angular-carousel.min.js | 4 +- index.html | 26 +++++++++ src/directives/rn-carousel-auto-slide.js | 44 ++++++++++++++ 4 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 src/directives/rn-carousel-auto-slide.js diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 5a59673..e747986 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.2 - 2014-04-02 + * @version v0.2.3 - 2014-07-08 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -19,6 +19,50 @@ angular.module('angular-carousel', [ angular.module('angular-carousel') +.directive('rnCarouselAutoSlide', ['$interval', function($interval) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), + timer = isPaused = increment = false; + + stopAutoplay = function () { + if (angular.isDefined(timer)) { + $interval.cancel(timer); + } + timer = undefined; + }; + + increment = function () { + if(!isPaused){ + if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { + scope.indicatorIndex++; + } else { + scope.indicatorIndex = 0; + } + } + + }; + + timer = $interval(increment, delay); + console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); + if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ + element.on('mouseenter', function(){ + stopAutoplay(); + }); + + element.on('mouseleave', function(){ + timer = $interval(increment, delay); + }); + } + + scope.$on('$destroy', stopAutoplay); + + } + }; +}]); +angular.module('angular-carousel') + .directive('rnCarouselControls', [function() { return { restrict: 'A', @@ -35,13 +79,18 @@ angular.module('angular-carousel') if (scope.index < scope.items.length-1) scope.index++; }; }, - template: '' + templateUrl: 'carousel-controls.html' }; }]); +angular.module('angular-carousel').run(['$templateCache', function($templateCache) { + $templateCache.put('carousel-controls.html', + '' + ); +}]); angular.module('angular-carousel') .directive('rnCarouselIndicators', [function() { @@ -52,12 +101,18 @@ angular.module('angular-carousel') items: '=', index: '=' }, - template: '' + templateUrl: 'carousel-indicators.html' }; }]); +angular.module('angular-carousel').run(['$templateCache', function($templateCache) { + $templateCache.put('carousel-indicators.html', + '' + ); +}]); + (function() { "use strict"; @@ -468,9 +523,7 @@ angular.module('angular-carousel') has3d, transforms = { 'webkitTransform':'-webkit-transform', - 'OTransform':'-o-transform', 'msTransform':'-ms-transform', - 'MozTransform':'-moz-transform', 'transform':'transform' }; // Add it to the body to get the computed style diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 0dbbed5..e8372d3 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.2 - 2014-04-02 + * @version v0.2.3 - 2014-07-08 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselControls",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},link:function(a){a.prev=function(){a.index--},a.next=function(){a.index++}},template:''}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},template:''}}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index 30f1cbb..fb0c716 100644 --- a/index.html +++ b/index.html @@ -122,6 +122,32 @@

                  Other demos

                • Flickr browser


                + +

                Autoplay slider

                +
                + By adding rn-carousel-auto-slide with an integer value will make the slider automatically change the visible slide after n seconds +
                + By adding rn-carousel-pause-on-hover="true" the slide will pause on mouse hover and start on mouse leave +
                +
                  +
                • + This is a standard template +
                  slide #1
                  +
                • +
                • + Here's sophie :
                  + +
                • +
                • + A friend of mine :
                  + +
                • +
                • + And to finish : + +
                • +
                +

                diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js new file mode 100644 index 0000000..4ad501f --- /dev/null +++ b/src/directives/rn-carousel-auto-slide.js @@ -0,0 +1,44 @@ +angular.module('angular-carousel') + +.directive('rnCarouselAutoSlide', ['$interval', function($interval) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), + timer = isPaused = increment = false; + + stopAutoplay = function () { + if (angular.isDefined(timer)) { + $interval.cancel(timer); + } + timer = undefined; + }; + + increment = function () { + if(!isPaused){ + if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { + scope.indicatorIndex++; + } else { + scope.indicatorIndex = 0; + } + } + + }; + + timer = $interval(increment, delay); + console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); + if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ + element.on('mouseenter', function(){ + stopAutoplay(); + }); + + element.on('mouseleave', function(){ + timer = $interval(increment, delay); + }); + } + + scope.$on('$destroy', stopAutoplay); + + } + }; +}]); \ No newline at end of file From 10ba52d4f481d98cdf3cfc012d2461e00c63f2ad Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Tue, 8 Jul 2014 15:18:11 +0300 Subject: [PATCH 071/159] removing console log --- dist/angular-carousel.js | 1 - dist/angular-carousel.min.js | 2 +- src/directives/rn-carousel-auto-slide.js | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e747986..eb5bff6 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -45,7 +45,6 @@ angular.module('angular-carousel') }; timer = $interval(increment, delay); - console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index e8372d3..c5013a3 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index 4ad501f..eaf4500 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -26,7 +26,6 @@ angular.module('angular-carousel') }; timer = $interval(increment, delay); - console.log('attrs.rnCarouselPauseOnHover',attrs.rnCarouselPauseOnHover); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); From 415d6c7145fdcfc62bac32a93b54a0f6bbd1eb52 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 14 Jul 2014 12:33:52 +0300 Subject: [PATCH 072/159] adding .idea to gitignore for ppl who use webstorm --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8260c04..90b4e22 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules bower_components coverage +.idea \ No newline at end of file From d8e272329a10a775923b6f871a24683e14ffcde5 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 14 Jul 2014 13:41:19 +0300 Subject: [PATCH 073/159] removing dependecy to indicator and adding support for carousel controlls --- dist/angular-carousel.js | 38 ++++++++++++++++-------- dist/angular-carousel.min.js | 4 +-- index.html | 2 +- src/directives/rn-carousel-auto-slide.js | 31 ++++++++++++------- src/directives/rn-carousel.js | 6 +++- 5 files changed, 53 insertions(+), 28 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index eb5bff6..c030cdb 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-08 + * @version v0.2.3 - 2014-07-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -19,39 +19,48 @@ angular.module('angular-carousel', [ angular.module('angular-carousel') -.directive('rnCarouselAutoSlide', ['$interval', function($interval) { +.directive('rnCarouselAutoSlide', ['$timeout', function($timeout) { return { restrict: 'A', link: function (scope, element, attrs) { var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), - timer = isPaused = increment = false; + timer = increment = false, slidesCount = element.children().length; + if(!scope.carouselExposedIndex){ + scope.carouselExposedIndex = 0; + } stopAutoplay = function () { if (angular.isDefined(timer)) { - $interval.cancel(timer); + $timeout.cancel(timer); } timer = undefined; }; increment = function () { - if(!isPaused){ - if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { - scope.indicatorIndex++; - } else { - scope.indicatorIndex = 0; - } + if (scope.carouselExposedIndex < slidesCount - 1) { + scope.carouselExposedIndex = scope.carouselExposedIndex + 1; + } else { + scope.carouselExposedIndex = 0; } + }; + restartTimer = function (){ + stopAutoplay(); + timer = $timeout(increment, delay); }; - timer = $interval(increment, delay); + scope.$watch('carouselIndex', function(){ + restartTimer(); + }); + + restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); }); element.on('mouseleave', function(){ - timer = $interval(increment, delay); + restartTimer(); }); } @@ -199,13 +208,16 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; + scope.carouselExposedIndex = newValue; }); scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); - } + scope.$watch('carouselExposedIndex', function(newValue) { + goToSlide(newValue, true); + }); // enable carousel indicator if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index c5013a3..a824116 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-08 + * @version v0.2.3 - 2014-07-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=isPaused=increment=!1;stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){isPaused||(b.indicatorIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index fb0c716..c13f388 100644 --- a/index.html +++ b/index.html @@ -129,7 +129,7 @@

                Autoplay slider


                By adding rn-carousel-pause-on-hover="true" the slide will pause on mouse hover and start on mouse leave -
                  +
                  • This is a standard template
                    slide #1
                    diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index eaf4500..7445eb2 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -1,38 +1,47 @@ angular.module('angular-carousel') -.directive('rnCarouselAutoSlide', ['$interval', function($interval) { +.directive('rnCarouselAutoSlide', ['$timeout', function($timeout) { return { restrict: 'A', link: function (scope, element, attrs) { var delay = Math.round(parseFloat(attrs.rnCarouselAutoSlide) * 1000), - timer = isPaused = increment = false; + timer = increment = false, slidesCount = element.children().length; + if(!scope.carouselExposedIndex){ + scope.carouselExposedIndex = 0; + } stopAutoplay = function () { if (angular.isDefined(timer)) { - $interval.cancel(timer); + $timeout.cancel(timer); } timer = undefined; }; increment = function () { - if(!isPaused){ - if (scope.indicatorIndex < scope.carouselIndicatorArray.length - 1) { - scope.indicatorIndex++; - } else { - scope.indicatorIndex = 0; - } + if (scope.carouselExposedIndex < slidesCount - 1) { + scope.carouselExposedIndex = scope.carouselExposedIndex + 1; + } else { + scope.carouselExposedIndex = 0; } + }; + restartTimer = function (){ + stopAutoplay(); + timer = $timeout(increment, delay); }; - timer = $interval(increment, delay); + scope.$watch('carouselIndex', function(){ + restartTimer(); + }); + + restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ element.on('mouseenter', function(){ stopAutoplay(); }); element.on('mouseleave', function(){ - timer = $interval(increment, delay); + restartTimer(); }); } diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 034f8b3..55ce32a 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -86,17 +86,21 @@ updateIndicatorArray(); scope.$watch('carouselIndex', function(newValue) { scope.indicatorIndex = newValue; + scope.carouselExposedIndex = newValue; }); scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); - } if (angular.isDefined(iAttributes.rnCarouselPreventAnimation)) { animOnIndexChange = false; } + scope.$watch('carouselExposedIndex', function(newValue) { + goToSlide(newValue, true); + }); + // enable carousel indicator if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); From 2bcb84761056e10dea852611dd16a39a13d0a93d Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 21 Jul 2014 17:46:17 +0300 Subject: [PATCH 074/159] removeing events on scope destroy --- src/directives/rn-carousel-auto-slide.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/directives/rn-carousel-auto-slide.js b/src/directives/rn-carousel-auto-slide.js index 7445eb2..6773b6b 100644 --- a/src/directives/rn-carousel-auto-slide.js +++ b/src/directives/rn-carousel-auto-slide.js @@ -36,16 +36,17 @@ angular.module('angular-carousel') restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ - element.on('mouseenter', function(){ - stopAutoplay(); - }); + element.on('mouseenter', stopAutoplay); - element.on('mouseleave', function(){ - restartTimer(); - }); + element.on('mouseleave', restartTimer); } - scope.$on('$destroy', stopAutoplay); + scope.$on('$destroy', function(){ + stopAutoplay(); + element.off('mouseenter', stopAutoplay); + element.off('mouseleave', restartTimer); + }); + } }; From 36825968ddc1326b58bed67a23cbb613331b53a3 Mon Sep 17 00:00:00 2001 From: Costica Puntaru Date: Mon, 21 Jul 2014 17:53:22 +0300 Subject: [PATCH 075/159] moving the demo before ``Other demos`` --- dist/angular-carousel.js | 17 +++++++++-------- dist/angular-carousel.min.js | 4 ++-- index.html | 12 ++++++------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index c030cdb..5fd365e 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-14 + * @version v0.2.3 - 2014-07-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -55,16 +55,17 @@ angular.module('angular-carousel') restartTimer(); if (attrs.rnCarouselPauseOnHover && attrs.rnCarouselPauseOnHover != 'false'){ - element.on('mouseenter', function(){ - stopAutoplay(); - }); + element.on('mouseenter', stopAutoplay); - element.on('mouseleave', function(){ - restartTimer(); - }); + element.on('mouseleave', restartTimer); } - scope.$on('$destroy', stopAutoplay); + scope.$on('$destroy', function(){ + stopAutoplay(); + element.off('mouseenter', stopAutoplay); + element.off('mouseleave', restartTimer); + }); + } }; diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index a824116..5d8559e 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-14 + * @version v0.2.3 - 2014-07-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index c13f388..235a15f 100644 --- a/index.html +++ b/index.html @@ -117,12 +117,6 @@

                    togglable carousel via ng-if

                  -

                  Other demos

                  - -

                  -

                  Autoplay slider

                  By adding rn-carousel-auto-slide with an integer value will make the slider automatically change the visible slide after n seconds @@ -148,6 +142,12 @@

                  Autoplay slider



                +

                Other demos

                + +

                + From eee5b6bb001f3e5fc03ba3dee5e179bca3057f74 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Mon, 21 Jul 2014 23:30:46 +0200 Subject: [PATCH 076/159] chore(readme): add auto-slide informations --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5acba04..1a4569d 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ angular.module('MyApp', ['angular-carousel']); - `rn-carousel-buffered` boolean value to enable the carousel buffering, good to minimize the DOM, defaults to 5 slides. (works only with arrays) - `rn-carousel-swipe` boolean value to enable/disable swiping (default true) - `rn-carousel-control` boolean value to enable builtin prev/next buttons (you can override by CSS) - + - `rn-carousel-auto-slide` integer value will make the slider automatically change the visible slide after given seconds + - `rn-carousel-pause-on-hover="true"` prevent auto-slide on hover + ## Todo : - see the [TODO file](./TODO) From aad80971bb98a3d5726c037e0944e1825ec7e2f0 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 24 Jul 2014 23:32:21 +0200 Subject: [PATCH 077/159] fix(indicator): prevent transition conflict with ngAnimate --- dist/angular-carousel.css | 3 +++ dist/angular-carousel.min.css | 2 +- src/css/angular-carousel.scss | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index d8c85fb..bbb22da 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -52,6 +52,9 @@ color: #333; } .rn-carousel-indicator span:before { content: "\25cf"; } + .rn-carousel-indicator span.ng-leave { + -webkit-transition: none !important; + transition: none !important; } .rn-carousel-indicator .active { color: white; } diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index bbbbae8..8a9d7dd 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden;position:relative}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator span.ng-leave{-webkit-transition:none!important;transition:none!important}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index c421131..849abef 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -53,6 +53,10 @@ $rn-carousel-control-height: 30px; &:before { content: "\25cf"; } + &.ng-leave { + // see https://github.com/revolunet/angular-carousel/issues/179 + transition: none !important; + } } .active { From 335ce4ea640991c8d16fec1be020418dcf067260 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 24 Jul 2014 23:52:51 +0200 Subject: [PATCH 078/159] chore: update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1a4569d..e8c9fc0 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ angular.module('MyApp', ['angular-carousel']); - `rn-carousel-control` boolean value to enable builtin prev/next buttons (you can override by CSS) - `rn-carousel-auto-slide` integer value will make the slider automatically change the visible slide after given seconds - `rn-carousel-pause-on-hover="true"` prevent auto-slide on hover + - `rn-carousel-prevent-animation="true"` if you dont want animations ## Todo : - see the [TODO file](./TODO) From debbbeb892e105a4fd6c13d4db88cc5c1b91b2f7 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Fri, 25 Jul 2014 00:09:14 +0200 Subject: [PATCH 079/159] feat(carousel): add prevent animation option --- TODO | 9 +++++---- bower.json | 2 +- dist/angular-carousel.css | 4 +++- dist/angular-carousel.js | 11 +++++++++-- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 ++-- package.json | 2 +- src/css/angular-carousel.scss | 2 ++ 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/TODO b/TODO index 8b248c1..e95331f 100644 --- a/TODO +++ b/TODO @@ -17,15 +17,16 @@ Carousel v2: Animations: ☐ should have some builtin animations ☐ should be able to customise animations - ☐ animation should occur on slides instead of container + ☐ animation should occur on individual slides instead of container + ☐ use % instead of pixels Bugs: ✔ bug when rn-carousel-index change while animation from outside @done (14-01-05 02:19) ☐ handle touch cancel ✔ initial index position not respected @done (14-01-07 23:51) Advanced: - ☐ optional cycle - ☐ infinite carousels with slide generators - ☐ optional auto-slide + ☐ optional loop + ☐ infinite carousels with slide generators (prev/next+load) + ✔ optional auto-slide @done (14-07-24 23:35) Tests: ✔ setup karma @done (14-01-05 00:15) Tooling: diff --git a/bower.json b/bower.json index 3c22ffc..c82068e 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.2.3", + "version": "0.2.4", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index bbb22da..9461d9e 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -2,7 +2,9 @@ /* general */ .rn-carousel-container { overflow: hidden; - position: relative; } + position: relative; + -ms-touch-action: none; + touch-action: none; } .rn-carousel-slides { -webkit-transform: translate3d(0, 0, 0); diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 5fd365e..1bc9173 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-21 + * @version v0.2.4 - 2014-07-25 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -197,6 +197,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach destination, slidesCount = 0, swipeMoved = false, + animOnIndexChange = true, // javascript based animation easing timestamp; @@ -214,11 +215,17 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach scope.$watch('indicatorIndex', function(newValue) { goToSlide(newValue, true); }); + + } + + if (angular.isDefined(iAttributes.rnCarouselPreventAnimation)) { + animOnIndexChange = false; } scope.$watch('carouselExposedIndex', function(newValue) { goToSlide(newValue, true); }); + // enable carousel indicator if (angular.isDefined(iAttributes.rnCarouselIndicator)) { var indicator = $compile("")(scope); @@ -256,7 +263,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach newValue = 0; updateParentIndex(newValue); } - goToSlide(newValue, true); + goToSlide(newValue, animOnIndexChange); } }); isIndexBound = true; diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index 8a9d7dd..cc56426 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -.rn-carousel-container{overflow:hidden;position:relative}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator span.ng-leave{-webkit-transition:none!important;transition:none!important}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +.rn-carousel-container{overflow:hidden;position:relative;-ms-touch-action:none;touch-action:none}.rn-carousel-slides{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}:root .rn-carousel-slides{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);position:relative;white-space:nowrap;overflow:visible;padding:0;margin:0}.rn-carousel-slide{white-space:normal;vertical-align:top;display:inline-block;width:100%;height:100%;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.rn-carousel-indicator{width:100%;text-align:center;height:20px;background-color:#000;background-color:rgba(0,0,0,.6);position:relative;bottom:0;cursor:pointer}.rn-carousel-indicator span{-webkit-transition:color .2s ease-out;transition:color .2s ease-out;padding:0 5px;color:#333}.rn-carousel-indicator span:before{content:"\25cf"}.rn-carousel-indicator span.ng-leave{-webkit-transition:none!important;transition:none!important}.rn-carousel-indicator .active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:30px;position:absolute;top:50%;margin-top:-35px;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 5d8559e..3525874 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.3 - 2014-07-21 + * @version v0.2.4 - 2014-07-25 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=S.children();return I=0===a.length?S[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){T.css("width","100%");var a=t();a&&T.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,S[0].style[J]=Y?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,void F(null,null,!0)):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),void v())}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=m.wrap(""),T=S.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var U=e("")(l);T.append(U)}if(angular.isDefined(n.rnCarouselControl)){var V=e("")(l);T.append(V)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var W=function(a){X.assign(l.$parent,a)},X=d(n.rnCarouselIndex);angular.isFunction(X.assign)?(l.$watch("carouselIndex",function(a){W(a)}),l.carouselIndex=X(l),l.$parent.$watch(X,function(a){void 0!==a&&(a>=Q?(a=Q-1,W(a)):0>a&&(a=0,W(a)),z(a,!0))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(S,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):S.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Y=G(),Z=angular.element(b);Z.bind("orientationchange",H),Z.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),Z.unbind("orientationchange",H),Z.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex0&&a.index--},a.next=function(){a.index\n \n \n')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=T.children();return I=0===a.length?T[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){U.css("width","100%");var a=t();a&&U.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,T[0].style[J]=Z?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,F(null,null,!0),void 0):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),v(),void 0)}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=!0,T=m.wrap(""),U=T.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselPreventAnimation)&&(S=!1),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var V=e("")(l);U.append(V)}if(angular.isDefined(n.rnCarouselControl)){var W=e("")(l);U.append(W)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var X=function(a){Y.assign(l.$parent,a)},Y=d(n.rnCarouselIndex);angular.isFunction(Y.assign)?(l.$watch("carouselIndex",function(a){X(a)}),l.carouselIndex=Y(l),l.$parent.$watch(Y,function(a){void 0!==a&&(a>=Q?(a=Q-1,X(a)):0>a&&(a=0,X(a)),z(a,S))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(T,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):T.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Z=G(),$=angular.element(b);$.bind("orientationchange",H),$.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),$.unbind("orientationchange",H),$.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index df5e797..0c1046e 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.2.3", + "version": "0.2.4", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index 849abef..f45ec95 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -6,6 +6,8 @@ $rn-carousel-control-height: 30px; .rn-carousel-container { overflow: hidden; position: relative; + -ms-touch-action: none; + touch-action: none; } .rn-carousel-slides { transform: translate3d(0,0,0); From 0ebcfd094d39cba11504619b9c14510a9df6aa60 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Fri, 25 Jul 2014 00:09:52 +0200 Subject: [PATCH 080/159] bump version --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index c82068e..ed277db 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.2.4", + "version": "0.2.5", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/package.json b/package.json index 0c1046e..5e7d626 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.2.4", + "version": "0.2.5", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From 755d3c7316c3c16d5f78c8e4f805bf4f9209c7ef Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Mon, 13 Oct 2014 04:52:02 +0200 Subject: [PATCH 081/159] refactor(carousel): transitions refactor : - single slide based transitions - externalize some services - use shifty.js for transitions - fix bunch of issues --- README.md | 39 +- TODO | 38 - bower.json | 2 +- demo/demo.css | 120 +- dist/angular-carousel.css | 97 +- dist/angular-carousel.js | 2298 +++++++++++++++++----- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 +- index.html | 267 +-- package.json | 2 +- src/angular-carousel.js | 3 +- src/css/angular-carousel.scss | 103 +- src/directives/rn-carousel-controls.js | 30 - src/directives/rn-carousel-indicators.js | 19 +- src/directives/rn-carousel.js | 866 ++++---- src/directives/shifty.js | 1383 +++++++++++++ 16 files changed, 3943 insertions(+), 1330 deletions(-) delete mode 100644 TODO delete mode 100755 src/directives/rn-carousel-controls.js create mode 100644 src/directives/shifty.js diff --git a/README.md b/README.md index f42df8e..c1b1af1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Comments and contributions welcome :) Proudly brought to you by the [@revolunet](http://twitter.com/revolunet) team. -**NOTE :** if you use IE<=9, iOS<7 or Android<4 please include the [requestAnimationFrame polyfill](https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js) in your application. ## Usage : @@ -28,7 +27,7 @@ angular.module('MyApp', ['angular-carousel']); - Add a `rn-carousel` attribute to your `
                  ` block and your `
                • `'s become magically swipable ;) ```html
                    -
                  • +
                  • {{ image }}
                  @@ -43,27 +42,31 @@ angular.module('MyApp', ['angular-carousel']);
                ``` +## Directive options : + - `rn-carousel-index` two way binding to control the carousel position (0-indexed) + - `rn-carousel-buffered` add this attribute to enable the carousel buffering, good to minimize the DOM (5 slides) + - `rn-carousel-controls` add this attribute to enable builtin prev/next buttons (you can override by CSS) + - `rn-carousel-auto-slide` add this attribute to make the carousel slide automatically after given seconds (default=3) + - `rn-carousel-transition` : transition type, can be one of `slide,zoom,hexagon,none,slideAndFade`. (default=slide) +## Indicators -## Features : - - Mobile friendly, tested on webkit+firefox - - Use CSS 3D transformations and `requestAnimationFrame`. (fallback to CSS 2D if 3D support not available) - - DOM buffering - - Index data-binding - - Optional indicators +You can add position indicators by adding this directive where you want : +```html +
                +``` + - `slides` is the same collection you use in the carousel ng-repeat + - `carouselIndex` is the same index you've defined for the carousel -### Regular carousel : - - `rn-carousel-index` two way binding to control the carousel position. - - `rn-carousel-indicator` boolean value to enable the indicator, see demo page. - - `rn-carousel-buffered` boolean value to enable the carousel buffering, good to minimize the DOM, defaults to 5 slides. (works only with arrays) - - `rn-carousel-swipe` boolean value to enable/disable swiping (default true) - - `rn-carousel-control` boolean value to enable builtin prev/next buttons (you can override by CSS) - - `rn-carousel-auto-slide` integer value will make the slider automatically change the visible slide after given seconds - - `rn-carousel-pause-on-hover="true"` prevent auto-slide on hover - - `rn-carousel-prevent-animation="true"` if you dont want animations +## Notes : + - if you use IE<=9, iOS<7 or Android<4 please include the [requestAnimationFrame polyfill](https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js) in your application. + - don't set any style attribute to your li's. they would be overwritten by the carousel (use classes instead). + - angular-carousel use the great [shifty.js](https://github.com/jeremyckahn/shifty) for the animations ## Todo : - - see the [TODO file](./TODO) + - customisable transitions + - more transition types + - infinite loop support ## Contributing - Please follow [AngularJS GIT conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#) diff --git a/TODO b/TODO deleted file mode 100644 index e95331f..0000000 --- a/TODO +++ /dev/null @@ -1,38 +0,0 @@ - - -Carousel v2: - Base features: - ✔ basic ngRepeat @done (14-01-04 20:22) - ✔ ngRepeat with filter @done (14-01-04 20:54) - ✔ ngRepeat with filter and track by @done (14-01-04 20:59) - ✔ template based only @done (14-01-04 20:22) - Bindings: - ✔ should have a carousel-index binding @done (14-01-04 20:22) - Buffering: - ✔ should optionnaly buffer the carousel DOM @done (14-01-04 20:22) - Indicators: - ✔ should have optional indicators @done (14-01-05 01:56) - ✔ indicators should be clickable @done (14-01-05 01:56) - ☐ indicators should be customizable - Animations: - ☐ should have some builtin animations - ☐ should be able to customise animations - ☐ animation should occur on individual slides instead of container - ☐ use % instead of pixels - Bugs: - ✔ bug when rn-carousel-index change while animation from outside @done (14-01-05 02:19) - ☐ handle touch cancel - ✔ initial index position not respected @done (14-01-07 23:51) - Advanced: - ☐ optional loop - ☐ infinite carousels with slide generators (prev/next+load) - ✔ optional auto-slide @done (14-07-24 23:35) - Tests: - ✔ setup karma @done (14-01-05 00:15) - Tooling: - ✔ update grunt @done (14-01-04 22:09) - ✔ add autoprefixer @done (14-01-04 22:09) - ☐ template with code samples for the demo page - ☐ automate version bump - Docs: - ✔ README update @done (14-01-05 02:19) diff --git a/bower.json b/bower.json index ed277db..0215d2e 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.2.5", + "version": "0.3.0", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/demo/demo.css b/demo/demo.css index 16cb5a4..58c3766 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -22,110 +22,42 @@ h3 { font-size:30px; margin: 30px 0 10px 0; } -.my-slider { - width: 450px; - height: 300px; - font-size:0; -} -.my-slider li { - box-sizing: border-box; - font-size:30px; - position:relative; + +.center { + text-align: center; } -.my-slider li div.debug { - box-sizing: border-box; - position:absolute; - bottom:0; - height:50px; - background:rgba(0,0,0,0.7); +.bgimage { + text-align:right; color:white; - font-size:12px; - width:100%; - padding:5px; + background-size:cover; + height: 100%; } -.my-slider.standard li { - text-align:center; - padding:20px; - font-size:20px; + +ul[rn-carousel] { + width:400px; + height:200px; + margin: 0 auto; } -.big { - margin-top:30px; + +.carousel5 li { width:100%; + height:100%; font-size:30px; + background-color: #ccc; } -.controls { - margin-top:5px; - width:450px; + +div.carousel-demo { + margin-top:20px; + display:inline-block; text-align: center; } -.ng-cloak { - display:none; -} -.center { - text-align:center; -} -.thumbs { - width:450px; + +input.tiny { + width:50px; text-align:center; } -.thumb { - display: inline-block; - background-size:cover; - border:1px solid transparent; - margin:2px 4px; - width:60px; - height:40px; - transition: border 0.2s ease-in; -} -.is-active { - border:1px solid red; -} -.details { - color:white; - font-size:12px; - margin-bottom:10px; -} -.button{ - display: inline-block; - text-decoration: none; - font: bold 12px/12px HelveticaNeue, Arial; - padding: 8px 11px; - color: #555; - border: 1px solid #dedede; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - cursor:pointer; -} -.button:disabled { - cursor: default !important; - color: #aaa !important; -} -.button.grey{ - background: #bdbdbd; - background: -webkit-gradient(linear, left top, left bottom, from(#cacaca), to(#aeaeae)); /* WebKit */ - background: -moz-linear-gradient(top, #cacaca, #aeaeae); - border-color: #b5b5b5 #a1a1a1 #8f8f8f; - color: #555; - text-shadow: 0 1px 0 #d4d4d4; -} -.button.grey:hover{ - background: #c2c2c2; - background: -webkit-gradient(linear, left top, left bottom, from(#bcbcbc), to(#c2c2c2)); /* WebKit */ - background: -moz-linear-gradient(top, #bcbcbc, #c2c2c2); - border-color: #989898 #8e8e8e #878787; - text-shadow: 0 1px 0 #dadada; -} -/* override default controls */ -.rn-carousel-control { - font-size:50px !important; - color:white; - opacity: 1; -} -.rn-carousel-control.rn-carousel-control-prev { - left: 5px; -} -.rn-carousel-control.rn-carousel-control-next { - right: 5px; + +ul[rn-carousel-transition="hexagon"] { + margin-left:100px; } diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index 9461d9e..80c3978 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -1,73 +1,58 @@ -/* variables */ -/* general */ -.rn-carousel-container { +body { + background: #ccc; } + +input[type=range] { + width: 300px; } + +ul[rn-carousel] { overflow: hidden; + padding: 0; + white-space: nowrap; position: relative; + -webkit-perspective: 1000px; + -ms-perspective: 1000px; + perspective: 1000px; -ms-touch-action: none; touch-action: none; } + ul[rn-carousel] li { + color: black; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + overflow: visible; + vertical-align: top; + position: absolute; + left: 0; + right: 0; + white-space: normal; + padding: 0; + margin: 0; + list-style-type: none; + width: 100%; + height: 100%; + display: inline-block; } -.rn-carousel-slides { - -webkit-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - position: relative; - white-space: nowrap; - overflow: visible; - padding: 0; - margin: 0; } +/* prevent flickering when moving buffer */ +ul[rn-carousel-buffered] li { + display: none; } -/* IE 9 */ -:root .rn-carousel-slides { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); - position: relative; - white-space: nowrap; - overflow: visible; - padding: 0; - margin: 0; } - -.rn-carousel-slide { - white-space: normal; - vertical-align: top; - display: inline-block; - width: 100%; - height: 100%; - -webkit-backface-visibility: hidden; - -ms-backface-visibility: hidden; - backface-visibility: hidden; } +ul[rn-carousel-transition="hexagon"] { + overflow: visible; } /* indicators */ -.rn-carousel-indicator { - width: 100%; - text-align: center; - height: 20px; - background-color: black; - background-color: rgba(0, 0, 0, 0.6); - position: relative; - bottom: 0; - cursor: pointer; } - .rn-carousel-indicator span { - -webkit-transition: color .2s ease-out; - transition: color .2s ease-out; - padding: 0 5px; - color: #333; } - .rn-carousel-indicator span:before { - content: "\25cf"; } - .rn-carousel-indicator span.ng-leave { - -webkit-transition: none !important; - transition: none !important; } - .rn-carousel-indicator .active { +div[rn-carousel-indicators] span { + cursor: pointer; + color: #666; } + div[rn-carousel-indicators] span.active { color: white; } -/* controls */ +/* prev/next controls */ .rn-carousel-control { -webkit-transition: opacity 0.2s ease-out; transition: opacity 0.2s ease-out; - font-size: 30px; + font-size: 2rem; position: absolute; - top: 50%; - margin-top: -35px; + top: 40%; opacity: 0.75; cursor: pointer; } .rn-carousel-control:hover { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 1bc9173..f08e401 100755 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.2.4 - 2014-07-25 + * @version v0.3.0 - 2014-10-13 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -14,7 +14,8 @@ http://github.com/revolunet/angular-carousel */ angular.module('angular-carousel', [ - 'ngTouch' + 'ngTouch', + 'angular-carousel.shifty' ]); angular.module('angular-carousel') @@ -72,52 +73,27 @@ angular.module('angular-carousel') }]); angular.module('angular-carousel') -.directive('rnCarouselControls', [function() { +.directive('rnCarouselIndicators', ['$parse', function($parse) { return { restrict: 'A', - replace: true, scope: { - items: '=', - index: '=' + slides: '=', + index: '=rnCarouselIndex' }, - link: function(scope, element, attrs) { - scope.prev = function() { - if (scope.index > 0) scope.index--; + templateUrl: 'carousel-indicators.html', + link: function(scope, iElement, iAttributes) { + var indexModel = $parse(iAttributes.rnCarouselIndex); + scope.goToSlide = function(index) { + indexModel.assign(scope.$parent.$parent, index); }; - scope.next = function() { - if (scope.index < scope.items.length-1) scope.index++; - }; - }, - templateUrl: 'carousel-controls.html' - }; -}]); - -angular.module('angular-carousel').run(['$templateCache', function($templateCache) { - $templateCache.put('carousel-controls.html', - '' - ); -}]); -angular.module('angular-carousel') - -.directive('rnCarouselIndicators', [function() { - return { - restrict: 'A', - replace: true, - scope: { - items: '=', - index: '=' - }, - templateUrl: 'carousel-indicators.html' + } }; }]); angular.module('angular-carousel').run(['$templateCache', function($templateCache) { $templateCache.put('carousel-indicators.html', - '')}]),angular.module("angular-carousel").directive("rnCarouselIndicators",[function(){return{restrict:"A",replace:!0,scope:{items:"=",index:"="},templateUrl:"carousel-indicators.html"}}]),angular.module("angular-carousel").run(["$templateCache",function(a){a.put("carousel-indicators.html",'')}]),function(){"use strict";angular.module("angular-carousel").directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$rootScope",function(a,b,c,d,e,f){var g=0,h=75,i=.05,j=3,k=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame;return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l.children()[0].attributes,q=!1,r=!1,s=!1;return l.addClass("rn-carousel-slides"),l.children().addClass("rn-carousel-slide"),["ng-repeat","data-ng-repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){for(var a=[],b=0;Q>b;b++)a[b]=b;l.carouselIndicatorArray=a}function t(){var a=T.children();return I=0===a.length?T[0].getBoundingClientRect().width:a[0].getBoundingClientRect().width}function u(){U.css("width","100%");var a=t();a&&U.css("width",a+"px")}function v(a){isNaN(a)&&(a=l.carouselIndex*I),P=a;var b=-Math.round(P);b+=l.carouselBufferIndex*I,T[0].style[J]=Z?"translate3d("+b+"px, 0, 0)":"translate("+b+"px, 0)"}function w(){var a,b;M&&(a=Date.now()-O,b=M*Math.exp(-a/h),b>j||-j>b?(v(N-b),k(w)):z(N/I))}function x(a){return a>=Q?Q:0>=a?0:a}function y(){var a=0,b=(l.carouselBufferSize-1)/2;r&&(a=l.carouselIndex<=b?0:QQ-l.carouselBufferSize?Q-l.carouselBufferSize:l.carouselIndex-b),l.carouselBufferIndex=a}function z(a,b){return isNaN(a)&&(a=l.carouselIndex),b?(P=a*I,F(null,null,!0),void 0):(l.carouselIndex=x(a),y(),"$apply"!==f.$$phase&&"$digest"!==f.$$phase&&(s?l.$apply():l.$digest()),v(),void 0)}function A(){return i*I}function B(a){R=!0,F({x:a.clientX,y:a.clientY},a)}function C(a){var b=a;return 0===l.carouselIndex?b=Math.max(-A(),b):l.carouselIndex===Q-1&&(b=Math.min((Q-1)*I+A(),b)),b}function D(a){return c.bind("mouseup",B),K=!0,L=a.x,M=0,O=Date.now(),!1}function E(a){var b,c;return K&&(b=a.x,c=L-b,(c>2||-2>c)&&(R=!0,L=b,k(function(){v(C(P+c))}))),!1}function F(a,b,d){if(!b||R){c.unbind("mouseup",B),K=!1,R=!1,N=P;var e=A(),f=l.carouselIndex*I,g=f-N,h=-Math[g>=0?"ceil":"floor"](g/I),i=Math.abs(g)>e;h+l.carouselIndex>=Q&&(h=Q-1-l.carouselIndex),h+l.carouselIndex<0&&(h=-l.carouselIndex);var j=i?h:0;return N=(j+l.carouselIndex)*I,M=N-P,O=Date.now(),d&&(M=P-f),k(w),!1}}function G(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}function H(){u(),z()}g++;var I,J,K,L,M,N,O,P=0,Q=0,R=!1,S=!0,T=m.wrap(""),U=T.parent();if((angular.isDefined(n.rnCarouselIndicator)||angular.isDefined(n.rnCarouselControl))&&(p(),l.$watch("carouselIndex",function(a){l.indicatorIndex=a,l.carouselExposedIndex=a}),l.$watch("indicatorIndex",function(a){z(a,!0)})),angular.isDefined(n.rnCarouselPreventAnimation)&&(S=!1),l.$watch("carouselExposedIndex",function(a){z(a,!0)}),angular.isDefined(n.rnCarouselIndicator)){var V=e("")(l);U.append(V)}if(angular.isDefined(n.rnCarouselControl)){var W=e("")(l);U.append(W)}if(l.carouselBufferIndex=0,l.carouselBufferSize=5,l.carouselIndex=0,n.rnCarouselIndex){var X=function(a){Y.assign(l.$parent,a)},Y=d(n.rnCarouselIndex);angular.isFunction(Y.assign)?(l.$watch("carouselIndex",function(a){X(a)}),l.carouselIndex=Y(l),l.$parent.$watch(Y,function(a){void 0!==a&&(a>=Q?(a=Q-1,X(a)):0>a&&(a=0,X(a)),z(a,S))}),s=!0):isNaN(n.rnCarouselIndex)||(l.carouselIndex=parseInt(n.rnCarouselIndex,10))}q?l.$watchCollection(o,function(a){Q=0,angular.isArray(a)?Q=a.length:angular.isObject(a)&&(Q=Object.keys(a).length),p(),I||u(),z(l.carouselIndex)}):(Q=m.children().length,p(),u()),n.$observe("rnCarouselSwipe",function(b){"false"!==b&&"off"!==b?a.bind(T,{start:D,move:E,end:F,cancel:function(a){F({},a)}}):T.unbind()}),s||z(l.carouselIndex),J="transform",["webkit","Moz","O","ms"].every(function(a){var b=a+"Transform";return"undefined"!=typeof document.body.style[b]?(J=b,!1):!0});var Z=G(),$=angular.element(b);$.bind("orientationchange",H),$.bind("resize",H),l.$on("$destroy",function(){c.unbind("mouseup",B),$.unbind("orientationchange",H),$.unbind("resize",H)})}}}}])}(),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0,l=.05;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li").attributes,r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(s=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("li")}function t(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b,c;c=100*m.carouselBufferIndex+a,angular.forEach(q(),function(a,d){b=i(h(d,c,I.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function v(a,b){if(1===k&&console.log("goToSlide",arguments,O),void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){return n[0].getBoundingClientRect().width}function x(){M=w()}function y(a){return c.bind("mouseup",t),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}function A(a,b){if((!b||L)&&(c.unbind("mouseup",t),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=l*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;s?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}k++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){1===k&&console.log("nextSlide, scope.carouselIndex",m.carouselIndex);var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,r||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){console.log("watch carouselIndex",a),O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;r&&m.$watchCollection(p,function(a){G=a,v(m.carouselIndex)}),m.$on("$destroy",function(){c.unbind("mouseup",t)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var V=angular.element(b);V.bind("orientationchange",C),V.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",t),V.unbind("orientationchange",C),V.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index 235a15f..c1de146 100644 --- a/index.html +++ b/index.html @@ -19,161 +19,127 @@

                AngularJS Touch Carousel

                Swipe these demos with your mouse or finger -

                ngRepeat demo (buffered carousel)

                -
                A simple buffered ng-repeat with a custom template. -
                - Swipe 50 slides with only 5 slides in the DOM -
                -
                  -
                • -
                  - {{ slide.label }} / {{ slides.length }} +
                  +
                  +

                  Buffered ngRepeat demo

                  +
                  A simple buffered ng-repeat with a custom template.
                  - carouselIndex: {{ carouselIndex }}
                  - carouselBufferIndex: {{ carouselBufferIndex }}
                  + Swipe 50 slides with only 5 slides in the DOM. use builtin controls
                  -
                • -
                - -

                template-based demo

                -
                Various blocks automagically converted to a carousel. + +
                +
                +

                ngRepeat with auto-slide, controls and indicators

                +
                +
                + +

                - Just add rn-carousel-indicator to display clickable indicators - -
                  -
                • - This is a standard template -
                  slide #1
                  -
                • -
                • - Here's sophie :
                  - -
                • -
                • - A friend of mine :
                  - -
                • -
                • - And to finish : - -
                • -
                - -

                Standard carousel with thumbs navigation

                -
                This one has an initial index and the thumbs controls the rn-carousel-index binding
                -
                  -
                • -
                -
                -
                -
                - -

                carousel with builtin prev/next controls

                -
                just add rn-carousel-control attribute to enable builtin controls
                -
                  -
                • -
                  - {{ slide.label }} / {{ slides.length }} +
                  +

                  ngRepeat with custom transition

                  +
                  Use the 'hexagon' transition. index is shared with the carousel below.
                  -
                • -
                - -

                buffered ngRepeat carousel with custom controls

                -
                Custom controls demo, just update the rn-carousel-index index binding
                -
                  -
                • -
                  - {{ slide.label }} / {{ slides4.length }} -
                  - carouselIndex: {{ carouselIndex }}
                  - carouselBufferIndex: {{ carouselBufferIndex }}
                  + -
                • -
                -
                - - {{ slideIndex + 1 }} / {{ slides4.length }} - - - -
                - -

                object-based ngRepeat carousel with indicators

                -
                Use the object-based ngRepeat syntax. (not compatible with buffering)
                -
                  -
                • -
                  {{ label }}
                  -
                • -
                - -

                togglable carousel via ng-if

                -
                If you use ng-if, be sure to use the dot-notation syntax for the index binding as it creates a child scope.
                - -

                - -
                  -
                • -
                  #{{ $index + 1 }}
                  -
                • -
                + +
                +
                +

                ngRepeat with custom transition

                +
                Use the 'zoom' transition. index is shared with the carousel above. +
                + +
                +
                +
                +

                Custom templates without ng-repeat and auto-slide

                +
                +
                + +
                -

                Autoplay slider

                -
                - By adding rn-carousel-auto-slide with an integer value will make the slider automatically change the visible slide after n seconds -
                - By adding rn-carousel-pause-on-hover="true" the slide will pause on mouse hover and start on mouse leave
                -
                  -
                • - This is a standard template -
                  slide #1
                  -
                • -
                • - Here's sophie :
                  - -
                • -
                • - A friend of mine :
                  - -
                • -
                • - And to finish : - -
                • -
                -

                -

                Other demos

                - -

                - - + - --> + + - - + + + + + + + + diff --git a/game.html b/game.html new file mode 100644 index 0000000..1af0df8 --- /dev/null +++ b/game.html @@ -0,0 +1,91 @@ + + + + + angular-carousel demo + + + + + + + + + + + + + + + + + From 605789a9a5a110a27b1b17c526ebe81e605e01cd Mon Sep 17 00:00:00 2001 From: justinsa Date: Mon, 13 Oct 2014 23:37:44 -0700 Subject: [PATCH 086/159] Allow angular version 1.3+ Angular came out with version 1.3.0 and these bower version strings do not respect the minor version change. --- bower.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bower.json b/bower.json index 3053843..3f1d2f5 100644 --- a/bower.json +++ b/bower.json @@ -16,10 +16,10 @@ "demo" ], "dependencies": { - "angular": "~1.2.10", - "angular-touch": "~1.2.10" + "angular": ">=1.2.10", + "angular-touch": ">=1.2.10" }, "devDependencies": { - "angular-mocks": "~1.2.10" + "angular-mocks": ">=1.2.10" } } From e2efb63977af6c3848ef725a5d65a2f4ae3b8459 Mon Sep 17 00:00:00 2001 From: Matt Groth Date: Tue, 14 Oct 2014 10:54:12 -0700 Subject: [PATCH 087/159] allow scroll-y on mobile if carousel is target --- dist/angular-carousel.css | 4 ++-- dist/angular-carousel.js | 2 +- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 ++-- src/css/angular-carousel.scss | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index aa9b9ba..9b65768 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -12,8 +12,8 @@ ul[rn-carousel] { -webkit-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px; - -ms-touch-action: none; - touch-action: none; } + -ms-touch-action: pan-y; + touch-action: pan-y; } ul[rn-carousel] li { color: black; -webkit-backface-visibility: hidden; diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index a6c92e6..42a5bee 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.1 - 2014-10-13 + * @version v0.3.1 - 2014-10-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index d6ad73a..50f9a52 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -body{background:#ccc}input[type=range]{width:300px}ul[rn-carousel]{overflow:hidden;padding:0;white-space:nowrap;position:relative;-webkit-perspective:1000px;-ms-perspective:1000px;perspective:1000px;-ms-touch-action:none;touch-action:none}ul[rn-carousel] li{color:#000;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;overflow:visible;vertical-align:top;position:absolute;left:0;right:0;white-space:normal;padding:0;margin:0;list-style-type:none;width:100%;height:100%;display:inline-block}ul[rn-carousel-buffered] li{display:none}ul[rn-carousel-transition=hexagon]{overflow:visible}div.rn-carousel-indicator span{cursor:pointer;color:#666}div.rn-carousel-indicator span.active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:2rem;position:absolute;top:40%;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +body{background:#ccc}input[type=range]{width:300px}ul[rn-carousel]{overflow:hidden;padding:0;white-space:nowrap;position:relative;-webkit-perspective:1000px;-ms-perspective:1000px;perspective:1000px;-ms-touch-action:pan-y;touch-action:pan-y}ul[rn-carousel] li{color:#000;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;overflow:visible;vertical-align:top;position:absolute;left:0;right:0;white-space:normal;padding:0;margin:0;list-style-type:none;width:100%;height:100%;display:inline-block}ul[rn-carousel-buffered] li{display:none}ul[rn-carousel-transition=hexagon]{overflow:visible}div.rn-carousel-indicator span{cursor:pointer;color:#666}div.rn-carousel-indicator span.active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:2rem;position:absolute;top:40%;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 8566131..5ff39f8 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.1 - 2014-10-13 + * @version v0.3.1 - 2014-10-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0,l=.05;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li").attributes,r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(s=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("li")}function t(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b,c;c=100*m.carouselBufferIndex+a,angular.forEach(q(),function(a,d){b=i(h(d,c,I.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function v(a,b){if(1===k&&console.log("goToSlide",arguments,O),void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){return n[0].getBoundingClientRect().width}function x(){M=w()}function y(a){return c.bind("mouseup",t),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}function A(a,b){if((!b||L)&&(c.unbind("mouseup",t),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=l*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;s?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}k++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){1===k&&console.log("nextSlide, scope.carouselIndex",m.carouselIndex);var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,r||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;r&&m.$watchCollection(p,function(a){G=a,v(m.carouselIndex)}),m.$on("$destroy",function(){c.unbind("mouseup",t)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var V=angular.element(b);V.bind("orientationchange",C),V.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",t),V.unbind("orientationchange",C),V.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0,l=.05;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li").attributes,r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(s=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("li")}function t(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b,c;c=100*m.carouselBufferIndex+a,angular.forEach(q(),function(a,d){b=i(h(d,c,I.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function v(a,b){if(1===k&&console.log("goToSlide",arguments,O),void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,void B();O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){return n[0].getBoundingClientRect().width}function x(){M=w()}function y(a){return c.bind("mouseup",t),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}function A(a,b){if((!b||L)&&(c.unbind("mouseup",t),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=l*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;s?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}k++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){1===k&&console.log("nextSlide, scope.carouselIndex",m.carouselIndex);var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,r||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;r&&m.$watchCollection(p,function(a){G=a,v(m.carouselIndex)}),m.$on("$destroy",function(){c.unbind("mouseup",t)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var V=angular.element(b);V.bind("orientationchange",C),V.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",t),V.unbind("orientationchange",C),V.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index a3e32d5..eb4f440 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -13,8 +13,8 @@ ul[rn-carousel] { white-space: nowrap; position: relative; perspective:1000px; - -ms-touch-action: none; - touch-action: none; + -ms-touch-action: pan-y; + touch-action: pan-y; li { color:black; backface-visibility: hidden; From 65610da4d039536b8a4a924bf4fed332e673ba31 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Tue, 14 Oct 2014 23:29:21 +0200 Subject: [PATCH 088/159] fix: add `rn-carousel-locked` binding + demo fix #217 --- README.md | 5 ++-- bower.json | 2 +- dist/angular-carousel.js | 51 ++++++++++++++++++++--------------- dist/angular-carousel.min.js | 4 +-- index.html | 16 +++++++++++ package.json | 2 +- src/directives/rn-carousel.js | 49 ++++++++++++++++++--------------- 7 files changed, 80 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 6652529..fe6562e 100644 --- a/README.md +++ b/README.md @@ -43,11 +43,12 @@ angular.module('MyApp', ['angular-carousel']); ``` ## Directive options : - - `rn-carousel-index` two way binding to control the carousel position (0-indexed) + - `rn-carousel-index` two way binding integer to control the carousel position (0-indexed) - `rn-carousel-buffered` add this attribute to enable the carousel buffering, good to minimize the DOM (5 slides) - `rn-carousel-controls` add this attribute to enable builtin prev/next buttons (you can override by CSS) - `rn-carousel-auto-slide` add this attribute to make the carousel slide automatically after given seconds (default=3) - - `rn-carousel-transition` : transition type, can be one of `slide,zoom,hexagon,none,slideAndFade`. (default=slide) + - `rn-carousel-transition` : transition type, can be one of `slide, zoom, hexagon, slideAndFade, none`. (default=slide) + - `rn-carousel-locked`: two way binding boolean that lock/unlock the carousel ## Indicators diff --git a/bower.json b/bower.json index 3053843..19dae4c 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.1", + "version": "0.3.2", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index a6c92e6..9c9616d 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.1 - 2014-10-13 + * @version v0.3.2 - 2014-10-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -208,8 +208,6 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach function($swipe, $window, $document, $parse, $compile, $timeout, $interval, computeCarouselSlideStyle, createStyleString, Tweenable) { // internal ids to allow multiple instances var carouselId = 0, - // in container % how much we need to drag to trigger the slide change - moveTreshold = 0.05, // in absolute pixels, at which distance the slide stick to the edge on release rubberTreshold = 3; @@ -265,7 +263,9 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach /* do touchend trigger next slide automatically */ isSequential: true, autoSlideDuration: 3, - bufferSize: 5 + bufferSize: 5, + /* in container % how much we need to drag to trigger the slide change */ + moveTreshold: 0.1 }; // TODO @@ -283,7 +283,8 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach elX = null, animateTransitions = true, intialState = true, - animating = false; + animating = false, + locked = false; if(iAttributes.rnCarouselControls!==undefined) { // dont use a directive for this @@ -331,14 +332,11 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach } scope.nextSlide = function(slideOptions) { - if (carouselId===1) { - console.log('nextSlide, scope.carouselIndex', scope.carouselIndex); - } var index = scope.carouselIndex + 1; if (index > currentSlides.length - 1) { index = 0; } - if (!animating) { + if (!locked) { goToSlide(index, slideOptions); } }; @@ -352,9 +350,6 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach }; function goToSlide(index, slideOptions) { - if (carouselId===1) { - console.log('goToSlide', arguments, animating); - } // move a to the given slide index if (index === undefined) { index = scope.carouselIndex; @@ -362,14 +357,14 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach slideOptions = slideOptions || {}; if (slideOptions.animate === false || options.transitionType === 'none') { - animating = false; + locked = false; offset = index * -100; scope.carouselIndex = index; updateBufferIndex(); return; } - animating = true; + locked = true; var tweenable = new Tweenable(); tweenable.tween({ from: { @@ -384,7 +379,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach updateSlidesPosition(state.x); }, finish: function() { - animating = false; + locked = false; scope.$apply(function() { scope.carouselIndex = index; offset = index * -100; @@ -414,6 +409,9 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach function swipeMove(coords, event) { //console.log('swipeMove', coords, event); + if (locked) { + return; + } var x, delta; if (pressed) { x = coords.x; @@ -442,7 +440,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach if (iAttributes.rnCarouselAutoSlide!==undefined) { var duration = parseInt(iAttributes.rnCarouselAutoSlide, 10) || options.autoSlideDuration; autoSlider = $interval(function() { - if (!animating && !pressed) { + if (!locked && !pressed) { scope.nextSlide(); } }, duration * 1000); @@ -456,7 +454,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach if (angular.isFunction(indexModel.assign)) { /* check if this property is assignable then watch it */ scope.$watch('carouselIndex', function(newValue) { - if (!animating) { + if (!locked) { updateParentIndex(newValue); } @@ -471,7 +469,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach newValue = 0; updateParentIndex(newValue); } - if (!animating) { + if (!locked) { goToSlide(newValue, { animate: !init }); @@ -493,14 +491,23 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach init = false; } + if (iAttributes.rnCarouselLocked) { + scope.$watch(iAttributes.rnCarouselLocked, function(newValue, oldValue) { + // only bind swipe when it's not switched off + if(newValue === true) { + locked = true; + } else { + locked = false; + } + }); + } + if (isRepeatBased) { scope.$watchCollection(repeatCollection, function(newValue, oldValue) { //console.log('repeatCollection', arguments); currentSlides = newValue; goToSlide(scope.carouselIndex); }); - } else { - } function swipeEnd(coords, event, forceAnimation) { @@ -517,12 +524,12 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach if (destination===0) { return; } - if (animating) { + if (locked) { return; } offset += (-destination * 100 / elWidth); if (options.isSequential) { - var minMove = moveTreshold * elWidth, + var minMove = options.moveTreshold * elWidth, absMove = -destination, slidesMove = -Math[absMove >= 0 ? 'ceil' : 'floor'](absMove / elWidth), shouldMove = Math.abs(absMove) > minMove; diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 8566131..5d2ed19 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.1 - 2014-10-13 + * @version v0.3.2 - 2014-10-14 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0,l=.05;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li").attributes,r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(s=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("li")}function t(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b,c;c=100*m.carouselBufferIndex+a,angular.forEach(q(),function(a,d){b=i(h(d,c,I.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function v(a,b){if(1===k&&console.log("goToSlide",arguments,O),void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){return n[0].getBoundingClientRect().width}function x(){M=w()}function y(a){return c.bind("mouseup",t),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}function A(a,b){if((!b||L)&&(c.unbind("mouseup",t),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=l*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;s?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}k++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){1===k&&console.log("nextSlide, scope.carouselIndex",m.carouselIndex);var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,r||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;r&&m.$watchCollection(p,function(a){G=a,v(m.carouselIndex)}),m.$on("$destroy",function(){c.unbind("mouseup",t)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var V=angular.element(b);V.bind("orientationchange",C),V.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",t),V.unbind("orientationchange",C),V.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li").attributes,q=!1,r=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("li")}function s(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b,c;c=100*l.carouselBufferIndex+a,angular.forEach(p(),function(a,d){b=i(h(d,c,H.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",s),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",s),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;r?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,q||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),q&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",s)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",s),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/index.html b/index.html index 28d3c55..34fd7b1 100644 --- a/index.html +++ b/index.html @@ -105,6 +105,22 @@

                Custom templates without ng-repeat and auto-slide

              +
              +
              +

              Lockable carousel

              +
              +
              + +
              diff --git a/package.json b/package.json index 8870c62..5f049c2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.1", + "version": "0.3.2", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index ea549bd..94e0f29 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -108,8 +108,6 @@ function($swipe, $window, $document, $parse, $compile, $timeout, $interval, computeCarouselSlideStyle, createStyleString, Tweenable) { // internal ids to allow multiple instances var carouselId = 0, - // in container % how much we need to drag to trigger the slide change - moveTreshold = 0.05, // in absolute pixels, at which distance the slide stick to the edge on release rubberTreshold = 3; @@ -165,7 +163,9 @@ /* do touchend trigger next slide automatically */ isSequential: true, autoSlideDuration: 3, - bufferSize: 5 + bufferSize: 5, + /* in container % how much we need to drag to trigger the slide change */ + moveTreshold: 0.1 }; // TODO @@ -183,7 +183,8 @@ elX = null, animateTransitions = true, intialState = true, - animating = false; + animating = false, + locked = false; if(iAttributes.rnCarouselControls!==undefined) { // dont use a directive for this @@ -231,14 +232,11 @@ } scope.nextSlide = function(slideOptions) { - if (carouselId===1) { - console.log('nextSlide, scope.carouselIndex', scope.carouselIndex); - } var index = scope.carouselIndex + 1; if (index > currentSlides.length - 1) { index = 0; } - if (!animating) { + if (!locked) { goToSlide(index, slideOptions); } }; @@ -252,9 +250,6 @@ }; function goToSlide(index, slideOptions) { - if (carouselId===1) { - console.log('goToSlide', arguments, animating); - } // move a to the given slide index if (index === undefined) { index = scope.carouselIndex; @@ -262,14 +257,14 @@ slideOptions = slideOptions || {}; if (slideOptions.animate === false || options.transitionType === 'none') { - animating = false; + locked = false; offset = index * -100; scope.carouselIndex = index; updateBufferIndex(); return; } - animating = true; + locked = true; var tweenable = new Tweenable(); tweenable.tween({ from: { @@ -284,7 +279,7 @@ updateSlidesPosition(state.x); }, finish: function() { - animating = false; + locked = false; scope.$apply(function() { scope.carouselIndex = index; offset = index * -100; @@ -314,6 +309,9 @@ function swipeMove(coords, event) { //console.log('swipeMove', coords, event); + if (locked) { + return; + } var x, delta; if (pressed) { x = coords.x; @@ -342,7 +340,7 @@ if (iAttributes.rnCarouselAutoSlide!==undefined) { var duration = parseInt(iAttributes.rnCarouselAutoSlide, 10) || options.autoSlideDuration; autoSlider = $interval(function() { - if (!animating && !pressed) { + if (!locked && !pressed) { scope.nextSlide(); } }, duration * 1000); @@ -356,7 +354,7 @@ if (angular.isFunction(indexModel.assign)) { /* check if this property is assignable then watch it */ scope.$watch('carouselIndex', function(newValue) { - if (!animating) { + if (!locked) { updateParentIndex(newValue); } @@ -371,7 +369,7 @@ newValue = 0; updateParentIndex(newValue); } - if (!animating) { + if (!locked) { goToSlide(newValue, { animate: !init }); @@ -393,14 +391,23 @@ init = false; } + if (iAttributes.rnCarouselLocked) { + scope.$watch(iAttributes.rnCarouselLocked, function(newValue, oldValue) { + // only bind swipe when it's not switched off + if(newValue === true) { + locked = true; + } else { + locked = false; + } + }); + } + if (isRepeatBased) { scope.$watchCollection(repeatCollection, function(newValue, oldValue) { //console.log('repeatCollection', arguments); currentSlides = newValue; goToSlide(scope.carouselIndex); }); - } else { - } function swipeEnd(coords, event, forceAnimation) { @@ -417,12 +424,12 @@ if (destination===0) { return; } - if (animating) { + if (locked) { return; } offset += (-destination * 100 / elWidth); if (options.isSequential) { - var minMove = moveTreshold * elWidth, + var minMove = options.moveTreshold * elWidth, absMove = -destination, slidesMove = -Math[absMove >= 0 ? 'ceil' : 'floor'](absMove / elWidth), shouldMove = Math.abs(absMove) > minMove; From 7123d0a1fda27fd02e83ddf418a07f3e307445a2 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Tue, 14 Oct 2014 23:55:05 +0200 Subject: [PATCH 089/159] feat(styles): use style.cssText --- dist/angular-carousel.js | 9 ++------- dist/angular-carousel.min.js | 2 +- src/directives/rn-carousel.js | 9 ++------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 9c9616d..eccb551 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -320,14 +320,9 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach function updateSlidesPosition(offset) { // manually apply transformation to carousel childrens // todo : optim : apply only to visible items - var style, x; - x = scope.carouselBufferIndex * 100 + offset; + var x = scope.carouselBufferIndex * 100 + offset; angular.forEach(getSlidesDOM(), function(child, index) { - style = createStyleString(computeCarouselSlideStyle(index, x, options.transitionType)); - if (child.getAttribute('style') !== style) { - child.setAttribute('style', style); - } - + child.style.cssText = createStyleString(computeCarouselSlideStyle(index, x, options.transitionType)); }); } diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 5d2ed19..90514a2 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li").attributes,q=!1,r=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("li")}function s(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b,c;c=100*l.carouselBufferIndex+a,angular.forEach(p(),function(a,d){b=i(h(d,c,H.transitionType)),a.getAttribute("style")!==b&&a.setAttribute("style",b)})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",s),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",s),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;r?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,q||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),q&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",s)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",s),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li").attributes,q=!1,r=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("li")}function s(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",s),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",s),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;r?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,q||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),q&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",s)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",s),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 94e0f29..f2865af 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -220,14 +220,9 @@ function updateSlidesPosition(offset) { // manually apply transformation to carousel childrens // todo : optim : apply only to visible items - var style, x; - x = scope.carouselBufferIndex * 100 + offset; + var x = scope.carouselBufferIndex * 100 + offset; angular.forEach(getSlidesDOM(), function(child, index) { - style = createStyleString(computeCarouselSlideStyle(index, x, options.transitionType)); - if (child.getAttribute('style') !== style) { - child.setAttribute('style', style); - } - + child.style.cssText = createStyleString(computeCarouselSlideStyle(index, x, options.transitionType)); }); } From 7335e1c844c0fac5ba0ae0b5f102f8c3d101bca5 Mon Sep 17 00:00:00 2001 From: Samuel Santos Date: Wed, 15 Oct 2014 16:27:05 +0100 Subject: [PATCH 090/159] Support inner
                elements inside slides AngularJS Touch Carousel should only animate and change CSS properties on direct carousel
              • children. Otherwise slides cannot contain other
                  elements. --- src/css/angular-carousel.scss | 4 ++-- src/directives/rn-carousel.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index eb4f440..d56bbb0 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -15,7 +15,7 @@ ul[rn-carousel] { perspective:1000px; -ms-touch-action: pan-y; touch-action: pan-y; - li { + > li { color:black; backface-visibility: hidden; overflow: visible; @@ -34,7 +34,7 @@ ul[rn-carousel] { } /* prevent flickering when moving buffer */ -ul[rn-carousel-buffered] li { +ul[rn-carousel-buffered] > li { display:none; } diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index f2865af..96a4d32 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -205,7 +205,7 @@ }); function getSlidesDOM() { - return iElement[0].querySelectorAll('li'); + return iElement[0].querySelectorAll(':scope > li'); } function documentMouseUpEvent(event) { From e7d04ff391afe9a3c2b11a670b907a8ee7ec0a57 Mon Sep 17 00:00:00 2001 From: Samuel Santos Date: Wed, 15 Oct 2014 17:27:20 +0100 Subject: [PATCH 091/159] Prevent error when carousel is hidden by ngIf When the carousel is hidden by ngIf the selector tElement[0].querySelector('li') returns null causing the following error: TypeError: Cannot read property 'attributes' of null at Object.compile (http://localhost:9000/bower_components/angular-carousel/dist/angular-carousel.js:221:79) at applyDirectivesToNode (http://localhost:9000/bower_components/angular/angular.js:6473:32) at compileNodes (http://localhost:9000/bower_components/angular/angular.js:6043:15) at compileNodes (http://localhost:9000/bower_components/angular/angular.js:6055:15) at compile (http://localhost:9000/bower_components/angular/angular.js:5976:15) at applyDirectivesToNode (http://localhost:9000/bower_components/angular/angular.js:6386:33) at compileNodes (http://localhost:9000/bower_components/angular/angular.js:6043:15) at compileNodes (http://localhost:9000/bower_components/angular/angular.js:6055:15) at compile (http://localhost:9000/bower_components/angular/angular.js:5976:15) at link (http://localhost:9000/bower_components/angular-route/angular-route.js:903:18)
                    --- src/directives/rn-carousel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 96a4d32..be0a781 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -118,7 +118,8 @@ scope: true, compile: function(tElement, tAttributes) { // use the compile phase to customize the DOM - var firstChildAttributes = tElement[0].querySelector('li').attributes, + var firstChild = tElement[0].querySelector('li'), + firstChildAttributes = (firstChild) ? firstChild.attributes : [], isRepeatBased = false, isBuffered = false, repeatItem, From 147c9daee2b533a182f2d10cbb8af322e7e7fd3a Mon Sep 17 00:00:00 2001 From: rdubigny Date: Thu, 16 Oct 2014 12:46:28 +0200 Subject: [PATCH 092/159] Update angular-carousel.scss --- src/css/angular-carousel.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index d56bbb0..cbc8034 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -1,8 +1,4 @@ -body { - background: #ccc; -} - input[type=range] { width:300px; } From 6082ed87ff0277333a2b702d5416878c21ea14d4 Mon Sep 17 00:00:00 2001 From: rdubigny Date: Thu, 16 Oct 2014 12:46:45 +0200 Subject: [PATCH 093/159] Update angular-carousel.scss --- src/css/angular-carousel.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/css/angular-carousel.scss b/src/css/angular-carousel.scss index cbc8034..905971f 100755 --- a/src/css/angular-carousel.scss +++ b/src/css/angular-carousel.scss @@ -1,4 +1,3 @@ - input[type=range] { width:300px; } From 27fb104d7dafb271afc90bc9891c07afc1ce646a Mon Sep 17 00:00:00 2001 From: rdubigny Date: Thu, 16 Oct 2014 12:47:23 +0200 Subject: [PATCH 094/159] Update angular-carousel.css --- dist/angular-carousel.css | 3 --- 1 file changed, 3 deletions(-) diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index 9b65768..cdc6524 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -1,6 +1,3 @@ -body { - background: #ccc; } - input[type=range] { width: 300px; } From 6b506613fed704a9336f0e15fac00b4809b98188 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 19 Oct 2014 00:45:16 +0200 Subject: [PATCH 095/159] bump 0.3.3 --- bower.json | 2 +- dist/angular-carousel.css | 4 ++-- dist/angular-carousel.js | 7 ++++--- dist/angular-carousel.min.css | 2 +- dist/angular-carousel.min.js | 4 ++-- package.json | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/bower.json b/bower.json index 9215b35..d768f2c 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.2", + "version": "0.3.3", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.css b/dist/angular-carousel.css index cdc6524..a11d852 100755 --- a/dist/angular-carousel.css +++ b/dist/angular-carousel.css @@ -11,7 +11,7 @@ ul[rn-carousel] { perspective: 1000px; -ms-touch-action: pan-y; touch-action: pan-y; } - ul[rn-carousel] li { + ul[rn-carousel] > li { color: black; -webkit-backface-visibility: hidden; -ms-backface-visibility: hidden; @@ -30,7 +30,7 @@ ul[rn-carousel] { display: inline-block; } /* prevent flickering when moving buffer */ -ul[rn-carousel-buffered] li { +ul[rn-carousel-buffered] > li { display: none; } ul[rn-carousel-transition="hexagon"] { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index dff9264..e4b7735 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.2 - 2014-10-15 + * @version v0.3.3 - 2014-10-19 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -218,7 +218,8 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach scope: true, compile: function(tElement, tAttributes) { // use the compile phase to customize the DOM - var firstChildAttributes = tElement[0].querySelector('li').attributes, + var firstChild = tElement[0].querySelector('li'), + firstChildAttributes = (firstChild) ? firstChild.attributes : [], isRepeatBased = false, isBuffered = false, repeatItem, @@ -305,7 +306,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach }); function getSlidesDOM() { - return iElement[0].querySelectorAll('li'); + return iElement[0].querySelectorAll(':scope > li'); } function documentMouseUpEvent(event) { diff --git a/dist/angular-carousel.min.css b/dist/angular-carousel.min.css index 50f9a52..0238d30 100644 --- a/dist/angular-carousel.min.css +++ b/dist/angular-carousel.min.css @@ -1 +1 @@ -body{background:#ccc}input[type=range]{width:300px}ul[rn-carousel]{overflow:hidden;padding:0;white-space:nowrap;position:relative;-webkit-perspective:1000px;-ms-perspective:1000px;perspective:1000px;-ms-touch-action:pan-y;touch-action:pan-y}ul[rn-carousel] li{color:#000;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;overflow:visible;vertical-align:top;position:absolute;left:0;right:0;white-space:normal;padding:0;margin:0;list-style-type:none;width:100%;height:100%;display:inline-block}ul[rn-carousel-buffered] li{display:none}ul[rn-carousel-transition=hexagon]{overflow:visible}div.rn-carousel-indicator span{cursor:pointer;color:#666}div.rn-carousel-indicator span.active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:2rem;position:absolute;top:40%;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file +input[type=range]{width:300px}ul[rn-carousel]{overflow:hidden;padding:0;white-space:nowrap;position:relative;-webkit-perspective:1000px;-ms-perspective:1000px;perspective:1000px;-ms-touch-action:pan-y;touch-action:pan-y}ul[rn-carousel]>li{color:#000;-webkit-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;overflow:visible;vertical-align:top;position:absolute;left:0;right:0;white-space:normal;padding:0;margin:0;list-style-type:none;width:100%;height:100%;display:inline-block}ul[rn-carousel-buffered]>li{display:none}ul[rn-carousel-transition=hexagon]{overflow:visible}div.rn-carousel-indicator span{cursor:pointer;color:#666}div.rn-carousel-indicator span.active{color:#fff}.rn-carousel-control{-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;font-size:2rem;position:absolute;top:40%;opacity:.75;cursor:pointer}.rn-carousel-control:hover{opacity:1}.rn-carousel-control.rn-carousel-control-prev{left:.5em}.rn-carousel-control.rn-carousel-control-prev:before{content:"<"}.rn-carousel-control.rn-carousel-control-next{right:.5em}.rn-carousel-control.rn-carousel-control-next:before{content:">"} \ No newline at end of file diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index def4dfa..15bdf74 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.2 - 2014-10-15 + * @version v0.3.3 - 2014-10-19 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li").attributes,q=!1,r=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=p[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(r=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),q=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("li")}function s(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",s),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",s),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;r?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,q||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),q&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",s)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",s),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll(":scope > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index 5f049c2..306edb7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.2", + "version": "0.3.3", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From ddfae392803d13f17708a11ed3c871293f8af87f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Oct 2014 18:59:57 +0800 Subject: [PATCH 096/159] fix return this.Tweenable is undefined --- src/directives/shifty.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/directives/shifty.js b/src/directives/shifty.js index 27fee91..c327e38 100644 --- a/src/directives/shifty.js +++ b/src/directives/shifty.js @@ -4,7 +4,7 @@ angular.module('angular-carousel.shifty', []) .factory('Tweenable', function() { - (function (root) { + (function (root, window) { /*! * Shifty Core * By Jeremy Kahn - jeremyckahn@gmail.com @@ -456,7 +456,8 @@ angular.module('angular-carousel.shifty', []) return Tweenable; } ()); - + + window.Tweenable = Tweenable; /*! * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). * @@ -1377,7 +1378,7 @@ angular.module('angular-carousel.shifty', []) } (Tweenable)); - }(this)); + }(this, window)); - return this.Tweenable; + return window.Tweenable; }); From 6393a0261f54a9352d08209614b7360546a8049d Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Mon, 20 Oct 2014 13:24:22 +0200 Subject: [PATCH 097/159] bump release --- bower.json | 2 +- dist/angular-carousel.js | 11 ++++++----- dist/angular-carousel.min.js | 4 ++-- package.json | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bower.json b/bower.json index d768f2c..cf9aeed 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.3", + "version": "0.3.4", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index e4b7735..6d561b3 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.3 - 2014-10-19 + * @version v0.3.4 - 2014-10-20 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -616,7 +616,7 @@ angular.module('angular-carousel.shifty', []) .factory('Tweenable', function() { - (function (root) { + (function (root, window) { /*! * Shifty Core * By Jeremy Kahn - jeremyckahn@gmail.com @@ -1068,7 +1068,8 @@ angular.module('angular-carousel.shifty', []) return Tweenable; } ()); - + + window.Tweenable = Tweenable; /*! * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). * @@ -1989,9 +1990,9 @@ angular.module('angular-carousel.shifty', []) } (Tweenable)); - }(this)); + }(this, window)); - return this.Tweenable; + return window.Tweenable; }); (function() { diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 15bdf74..d17bc54 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.3 - 2014-10-19 + * @version v0.3.4 - 2014-10-20 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll(":scope > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,a.isPlaying()&&!u?(k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d)):u&&(j(g),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=r();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,a&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(this),this.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll(":scope > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index 306edb7..d68354e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.3", + "version": "0.3.4", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From ba4bf9dc93c4b2748c3a20c9137f22ec4193f5a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Dubigny?= Date: Tue, 21 Oct 2014 15:17:47 +0200 Subject: [PATCH 098/159] feat (directive): IE8 Support --- src/directives/rn-carousel.js | 90 +++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index be0a781..884b758 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -8,14 +8,18 @@ // detect supported CSS property function detectTransformProperty() { var transformProperty = 'transform'; - ['webkit', 'moz', 'o', 'ms'].every(function(prefix) { - var e = '-' + prefix + '-transform'; - if (typeof document.body.style[e] !== 'undefined') { - transformProperty = e; - return false; - } - return true; - }); + if (typeof document.body.style[transformProperty] !== 'undefined') { + ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { + var e = '-' + prefix + '-transform'; + if (typeof document.body.style[e] !== 'undefined') { + transformProperty = e; + return false; + } + return true; + }); + } else { + transformProperty = undefined; + } return transformProperty; } @@ -58,37 +62,42 @@ slideTransformValue = DeviceCapabilities.has3d ? 'translate3d(' + absoluteLeft + '%, 0, 0)' : 'translate3d(' + absoluteLeft + '%, 0)', distance = ((100 - Math.abs(absoluteLeft)) / 100); - if (transitionType == 'fadeAndSlide') { - style[DeviceCapabilities.transformProperty] = slideTransformValue; - opacity = 0; - if (Math.abs(absoluteLeft) < 100) { - opacity = 0.3 + distance * 0.7; - } - style.opacity = opacity; - } else if (transitionType == 'hexagon') { - var transformFrom = 100, - degrees = 0, - maxDegrees = 60 * (distance - 1); - - transformFrom = offset < (slideIndex * -100) ? 100 : 0; - degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; - style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; - style['transform-origin'] = transformFrom + '% 50%'; - } else if (transitionType == 'zoom') { - style[DeviceCapabilities.transformProperty] = slideTransformValue; - var scale = 1; - if (Math.abs(absoluteLeft) < 100) { - scale = 1 + ((1 - distance) * 2); - } - style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; - style['transform-origin'] = '50% 50%'; - opacity = 0; - if (Math.abs(absoluteLeft) < 100) { - opacity = 0.3 + distance * 0.7; - } - style.opacity = opacity; + if (!DeviceCapabilities.transformProperty) { + // fallback to default slide if transformProperty is not available + style['margin-left'] = absoluteLeft + '%'; } else { - style[DeviceCapabilities.transformProperty] = slideTransformValue; + if (transitionType == 'fadeAndSlide') { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + opacity = 0; + if (Math.abs(absoluteLeft) < 100) { + opacity = 0.3 + distance * 0.7; + } + style.opacity = opacity; + } else if (transitionType == 'hexagon') { + var transformFrom = 100, + degrees = 0, + maxDegrees = 60 * (distance - 1); + + transformFrom = offset < (slideIndex * -100) ? 100 : 0; + degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; + style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; + style['transform-origin'] = transformFrom + '% 50%'; + } else if (transitionType == 'zoom') { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + var scale = 1; + if (Math.abs(absoluteLeft) < 100) { + scale = 1 + ((1 - distance) * 2); + } + style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; + style['transform-origin'] = '50% 50%'; + opacity = 0; + if (Math.abs(absoluteLeft) < 100) { + opacity = 0.3 + distance * 0.7; + } + style.opacity = opacity; + } else { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + } } return style; }; @@ -206,7 +215,7 @@ }); function getSlidesDOM() { - return iElement[0].querySelectorAll(':scope > li'); + return iElement[0].querySelectorAll('ul[rn-carousel] > li'); } function documentMouseUpEvent(event) { @@ -286,7 +295,8 @@ } function getContainerWidth() { - return iElement[0].getBoundingClientRect().width; + var rect = iElement[0].getBoundingClientRect(); + return rect.width ? rect.width : rect.right - rect.left; } function updateContainerWidth() { From 568f6286fd325f6d16e94ffec4cffca6157f1059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Dubigny?= Date: Tue, 21 Oct 2014 15:49:02 +0200 Subject: [PATCH 099/159] docs (directive): IE8 Support --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fe6562e..751c21b 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ You can add position indicators by adding this directive where you want : ## Notes : - if you use IE<=9, iOS<7 or Android<4 please include the [requestAnimationFrame polyfill](https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js) in your application. + - if you use IE<=8 include the [es5-shim polyfill](https://github.com/es-shims/es5-shim/blob/master/es5-shim.min.js) in your application. - don't set any style attribute to your li's. they would be overwritten by the carousel (use classes instead). - angular-carousel use the great [shifty.js](https://github.com/jeremyckahn/shifty) for the animations From 82f61f26c932132ad515324a10bf1380a061b194 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Tue, 21 Oct 2014 18:00:07 +0200 Subject: [PATCH 100/159] bump release --- bower.json | 2 +- dist/angular-carousel.js | 92 ++++++++++++++++++++---------------- dist/angular-carousel.min.js | 4 +- package.json | 2 +- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/bower.json b/bower.json index cf9aeed..0142ec0 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.4", + "version": "0.3.5", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 6d561b3..60bf2a5 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.4 - 2014-10-20 + * @version v0.3.5 - 2014-10-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -108,14 +108,18 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach // detect supported CSS property function detectTransformProperty() { var transformProperty = 'transform'; - ['webkit', 'moz', 'o', 'ms'].every(function(prefix) { - var e = '-' + prefix + '-transform'; - if (typeof document.body.style[e] !== 'undefined') { - transformProperty = e; - return false; - } - return true; - }); + if (typeof document.body.style[transformProperty] !== 'undefined') { + ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { + var e = '-' + prefix + '-transform'; + if (typeof document.body.style[e] !== 'undefined') { + transformProperty = e; + return false; + } + return true; + }); + } else { + transformProperty = undefined; + } return transformProperty; } @@ -158,37 +162,42 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach slideTransformValue = DeviceCapabilities.has3d ? 'translate3d(' + absoluteLeft + '%, 0, 0)' : 'translate3d(' + absoluteLeft + '%, 0)', distance = ((100 - Math.abs(absoluteLeft)) / 100); - if (transitionType == 'fadeAndSlide') { - style[DeviceCapabilities.transformProperty] = slideTransformValue; - opacity = 0; - if (Math.abs(absoluteLeft) < 100) { - opacity = 0.3 + distance * 0.7; - } - style.opacity = opacity; - } else if (transitionType == 'hexagon') { - var transformFrom = 100, - degrees = 0, - maxDegrees = 60 * (distance - 1); - - transformFrom = offset < (slideIndex * -100) ? 100 : 0; - degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; - style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; - style['transform-origin'] = transformFrom + '% 50%'; - } else if (transitionType == 'zoom') { - style[DeviceCapabilities.transformProperty] = slideTransformValue; - var scale = 1; - if (Math.abs(absoluteLeft) < 100) { - scale = 1 + ((1 - distance) * 2); - } - style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; - style['transform-origin'] = '50% 50%'; - opacity = 0; - if (Math.abs(absoluteLeft) < 100) { - opacity = 0.3 + distance * 0.7; - } - style.opacity = opacity; + if (!DeviceCapabilities.transformProperty) { + // fallback to default slide if transformProperty is not available + style['margin-left'] = absoluteLeft + '%'; } else { - style[DeviceCapabilities.transformProperty] = slideTransformValue; + if (transitionType == 'fadeAndSlide') { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + opacity = 0; + if (Math.abs(absoluteLeft) < 100) { + opacity = 0.3 + distance * 0.7; + } + style.opacity = opacity; + } else if (transitionType == 'hexagon') { + var transformFrom = 100, + degrees = 0, + maxDegrees = 60 * (distance - 1); + + transformFrom = offset < (slideIndex * -100) ? 100 : 0; + degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; + style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; + style['transform-origin'] = transformFrom + '% 50%'; + } else if (transitionType == 'zoom') { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + var scale = 1; + if (Math.abs(absoluteLeft) < 100) { + scale = 1 + ((1 - distance) * 2); + } + style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; + style['transform-origin'] = '50% 50%'; + opacity = 0; + if (Math.abs(absoluteLeft) < 100) { + opacity = 0.3 + distance * 0.7; + } + style.opacity = opacity; + } else { + style[DeviceCapabilities.transformProperty] = slideTransformValue; + } } return style; }; @@ -306,7 +315,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach }); function getSlidesDOM() { - return iElement[0].querySelectorAll(':scope > li'); + return iElement[0].querySelectorAll('ul[rn-carousel] > li'); } function documentMouseUpEvent(event) { @@ -386,7 +395,8 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach } function getContainerWidth() { - return iElement[0].getBoundingClientRect().width; + var rect = iElement[0].getBoundingClientRect(); + return rect.width ? rect.width : rect.right - rect.left; } function updateContainerWidth() { diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index d17bc54..ee35e4d 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.4 - 2014-10-20 + * @version v0.3.5 - 2014-10-21 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}),a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll(":scope > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){return m[0].getBoundingClientRect().width}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a=void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index d68354e..8752676 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.4", + "version": "0.3.5", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From a25444439c0725c25a15daa37231dd7ae66c5b3b Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 30 Oct 2014 03:10:20 +0100 Subject: [PATCH 101/159] docs: fix readme typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 751c21b..77dd5c2 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ angular.module('MyApp', ['angular-carousel']); - `rn-carousel-buffered` add this attribute to enable the carousel buffering, good to minimize the DOM (5 slides) - `rn-carousel-controls` add this attribute to enable builtin prev/next buttons (you can override by CSS) - `rn-carousel-auto-slide` add this attribute to make the carousel slide automatically after given seconds (default=3) - - `rn-carousel-transition` : transition type, can be one of `slide, zoom, hexagon, slideAndFade, none`. (default=slide) + - `rn-carousel-transition` : transition type, can be one of `slide, zoom, hexagon, fadeAndSlide, none`. (default=slide) - `rn-carousel-locked`: two way binding boolean that lock/unlock the carousel ## Indicators From dcf34a6cb76c35a14e268305be054d9cbc5fafda Mon Sep 17 00:00:00 2001 From: Sanborn Date: Thu, 6 Nov 2014 14:08:46 -0500 Subject: [PATCH 102/159] Fix for detecting safari transform property --- src/directives/rn-carousel.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 884b758..0fbc21f 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -7,8 +7,11 @@ // detect supported CSS property function detectTransformProperty() { - var transformProperty = 'transform'; - if (typeof document.body.style[transformProperty] !== 'undefined') { + var transformProperty = 'transform', + safariPropertyHack = 'webkitTransform'; + if (typeof document.body.style[transformProperty] !== 'undefined' && + typeof document.body.style[safariPropertyHack] !== 'undefined') { + ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { var e = '-' + prefix + '-transform'; if (typeof document.body.style[e] !== 'undefined') { @@ -17,6 +20,8 @@ } return true; }); + } else if (typeof document.body.style[safariPropertyHack] !== 'undefined') { + transformProperty = '-webkit-transform'; } else { transformProperty = undefined; } From 20f6e24baaf884a8b8646b5ce6a4ad8701558b2e Mon Sep 17 00:00:00 2001 From: Sanborn Date: Thu, 6 Nov 2014 14:13:43 -0500 Subject: [PATCH 103/159] Build with safari fix --- dist/angular-carousel.js | 11 ++++++++--- dist/angular-carousel.min.js | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 60bf2a5..665a923 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.5 - 2014-10-21 + * @version v0.3.5 - 2014-11-06 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -107,8 +107,11 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach // detect supported CSS property function detectTransformProperty() { - var transformProperty = 'transform'; - if (typeof document.body.style[transformProperty] !== 'undefined') { + var transformProperty = 'transform', + safariPropertyHack = 'webkitTransform'; + if (typeof document.body.style[transformProperty] !== 'undefined' && + typeof document.body.style[safariPropertyHack] !== 'undefined') { + ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { var e = '-' + prefix + '-transform'; if (typeof document.body.style[e] !== 'undefined') { @@ -117,6 +120,8 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach } return true; }); + } else if (typeof document.body.style[safariPropertyHack] !== 'undefined') { + transformProperty = '-webkit-transform'; } else { transformProperty = undefined; } diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index ee35e4d..eafe81e 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.5 - 2014-10-21 + * @version v0.3.5 - 2014-11-06 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a=void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,A(),void 0;N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]&&"undefined"!=typeof document.body.style[b]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,void A();N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file From 91fe66d77af11821156cf3cbc23b336dd30c1c97 Mon Sep 17 00:00:00 2001 From: Sanborn Date: Thu, 6 Nov 2014 14:35:25 -0500 Subject: [PATCH 104/159] Removed uncessary condition in detectTransformProperty --- dist/angular-carousel.js | 3 +-- dist/angular-carousel.min.js | 2 +- src/directives/rn-carousel.js | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 665a923..d919366 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -109,8 +109,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach function detectTransformProperty() { var transformProperty = 'transform', safariPropertyHack = 'webkitTransform'; - if (typeof document.body.style[transformProperty] !== 'undefined' && - typeof document.body.style[safariPropertyHack] !== 'undefined') { + if (typeof document.body.style[transformProperty] !== 'undefined') { ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { var e = '-' + prefix + '-transform'; diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index eafe81e..ed33567 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]&&"undefined"!=typeof document.body.style[b]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,void A();N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,void A();N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 0fbc21f..99c8ea7 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -9,8 +9,7 @@ function detectTransformProperty() { var transformProperty = 'transform', safariPropertyHack = 'webkitTransform'; - if (typeof document.body.style[transformProperty] !== 'undefined' && - typeof document.body.style[safariPropertyHack] !== 'undefined') { + if (typeof document.body.style[transformProperty] !== 'undefined') { ['webkit', 'moz', 'o', 'ms'].every(function (prefix) { var e = '-' + prefix + '-transform'; From 0578ae4c2e4484a81043f3cb64917176fa9f3bd3 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 6 Nov 2014 21:32:41 +0100 Subject: [PATCH 105/159] fix(hexagon): fix #232 --- src/directives/rn-carousel.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 99c8ea7..0a267e6 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -5,6 +5,8 @@ .service('DeviceCapabilities', function() { + // TODO: merge in a single function + // detect supported CSS property function detectTransformProperty() { var transformProperty = 'transform', @@ -85,7 +87,7 @@ transformFrom = offset < (slideIndex * -100) ? 100 : 0; degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; - style['transform-origin'] = transformFrom + '% 50%'; + style[DeviceCapabilities.transformProperty + '-origin'] = transformFrom + '% 50%'; } else if (transitionType == 'zoom') { style[DeviceCapabilities.transformProperty] = slideTransformValue; var scale = 1; @@ -93,7 +95,7 @@ scale = 1 + ((1 - distance) * 2); } style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; - style['transform-origin'] = '50% 50%'; + style[DeviceCapabilities.transformProperty + '-origin'] = '50% 50%'; opacity = 0; if (Math.abs(absoluteLeft) < 100) { opacity = 0.3 + distance * 0.7; From 6ff425daa389a7b9ba5138a740f14fa1dd0e05fe Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 6 Nov 2014 23:13:34 +0100 Subject: [PATCH 106/159] feat(carousel): add rn-carousel-deep-watch --- README.md | 1 + index.html | 52 +++++++++++++++++++++++++++++++---- src/directives/rn-carousel.js | 33 +++++++++++++++++++--- 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 77dd5c2..484cc91 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ angular.module('MyApp', ['angular-carousel']); - `rn-carousel-auto-slide` add this attribute to make the carousel slide automatically after given seconds (default=3) - `rn-carousel-transition` : transition type, can be one of `slide, zoom, hexagon, fadeAndSlide, none`. (default=slide) - `rn-carousel-locked`: two way binding boolean that lock/unlock the carousel + - `rn-carousel-deep-watch`: Deep watch the collection which enable to dynamically add slides at beginning without corrupting position ## Indicators diff --git a/index.html b/index.html index 34fd7b1..3776ae5 100644 --- a/index.html +++ b/index.html @@ -109,6 +109,7 @@

                    Custom templates without ng-repeat and auto-slide

                    Lockable carousel

                    + use rn-carousel-locked binding to dynamically lock/unlock the carousel
                  +
                  +
                  +

                  Add/Remove items in the collection

                  +
                  + The carousel is bound to your ngRepeat collection.
                  + If you add items at the start of the collection, then by default, the slide position will change.
                  + If you want to preserve position even when adding items at the head of the collection, you need to add the `rn-carousel-deep-watch` attribute. This has a performance impact so use carefully.
                  + Works great with buffering too so you can have almost infinite slides while keeping only 5 items in the DOM
                  +
                  + +
                  - +

                   

                  +

                   

                  @@ -144,15 +168,19 @@

                  Lockable carousel

                  $scope.colors = ["#fc0003", "#f70008", "#f2000d", "#ed0012", "#e80017", "#e3001c", "#de0021", "#d90026", "#d4002b", "#cf0030", "#c90036", "#c4003b", "#bf0040", "#ba0045", "#b5004a", "#b0004f", "#ab0054", "#a60059", "#a1005e", "#9c0063", "#960069", "#91006e", "#8c0073", "#870078", "#82007d", "#7d0082", "#780087", "#73008c", "#6e0091", "#690096", "#63009c", "#5e00a1", "#5900a6", "#5400ab", "#4f00b0", "#4a00b5", "#4500ba", "#4000bf", "#3b00c4", "#3600c9", "#3000cf", "#2b00d4", "#2600d9", "#2100de", "#1c00e3", "#1700e8", "#1200ed", "#0d00f2", "#0800f7", "#0300fc"]; - function addSlide(target, style) { + function getSlide(target, style) { var i = target.length; - target.push({ + return { id: (i + 1), label: 'slide #' + (i + 1), img: 'http://lorempixel.com/450/300/' + style + '/' + ((i + 1) % 10) , color: $scope.colors[ (i*10) % $scope.colors.length], odd: (i % 2 === 0) - }); + }; + } + + function addSlide(target, style) { + target.push(getSlide(target, style)); }; $scope.carouselIndex = 3; @@ -183,7 +211,21 @@

                  Lockable carousel

                  $scope.slides4 = []; addSlides($scope.slides4, 'city', 50); - }); + + // 5th ngRepeat demo + $scope.slides6 = []; + $scope.carouselIndex6 = 0; + addSlides($scope.slides6, 'sports', 10); + $scope.addSlide = function(at) { + if(at==='head') { + $scope.slides6.unshift(getSlide($scope.slides6, 'people')); + } else { + $scope.slides6.push(getSlide($scope.slides6, 'people')); + } + } + + }) + diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 0a267e6..84c756c 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -128,6 +128,18 @@ var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame; + function getItemIndex(collection, target, defaultIndex) { + var result = defaultIndex; + collection.every(function(item, index) { + if (angular.equals(item, target)) { + result = index; + return false; + } + return true; + }); + return result; + }; + return { restrict: 'A', scope: true, @@ -261,6 +273,7 @@ }; function goToSlide(index, slideOptions) { + //console.log('goToSlide', arguments); // move a to the given slide index if (index === undefined) { index = scope.carouselIndex; @@ -415,11 +428,23 @@ } if (isRepeatBased) { - scope.$watchCollection(repeatCollection, function(newValue, oldValue) { - //console.log('repeatCollection', arguments); + // use rn-carousel-deep-watch to fight the Angular $watchCollection weakness : https://github.com/angular/angular.js/issues/2621 + // optional because it have some performance impacts (deep watch) + var deepWatch = (iAttributes.rnCarouselDeepWatch!==undefined); + + scope[deepWatch?'$watch':'$watchCollection'](repeatCollection, function(newValue, oldValue) { + //console.log('repeatCollection', currentSlides); + var oldSlides = (currentSlides || newValue).slice(); currentSlides = newValue; - goToSlide(scope.carouselIndex); - }); + // if deepWatch ON ,manually compare objects to guess the new position + if (deepWatch && angular.isArray(newValue)) { + var activeElement = oldValue[scope.carouselIndex]; + var newIndex = getItemIndex(newValue, activeElement, scope.carouselIndex); + goToSlide(newIndex, {animate: false}); + } else { + goToSlide(scope.carouselIndex, {animate: false}); + } + }, true); } function swipeEnd(coords, event, forceAnimation) { From 6d83767719401a4f98968b985851e56b5bc38442 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 6 Nov 2014 23:27:37 +0100 Subject: [PATCH 107/159] bump 0.3.6 --- bower.json | 2 +- dist/angular-carousel.js | 39 ++++++++++++++++++++++++++++++------ dist/angular-carousel.min.js | 2 +- package.json | 2 +- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/bower.json b/bower.json index 0142ec0..dd01b6a 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.5", + "version": "0.3.6", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index d919366..35fa6be 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -105,6 +105,8 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach .service('DeviceCapabilities', function() { + // TODO: merge in a single function + // detect supported CSS property function detectTransformProperty() { var transformProperty = 'transform', @@ -185,7 +187,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach transformFrom = offset < (slideIndex * -100) ? 100 : 0; degrees = offset < (slideIndex * -100) ? maxDegrees : -maxDegrees; style[DeviceCapabilities.transformProperty] = slideTransformValue + ' ' + 'rotateY(' + degrees + 'deg)'; - style['transform-origin'] = transformFrom + '% 50%'; + style[DeviceCapabilities.transformProperty + '-origin'] = transformFrom + '% 50%'; } else if (transitionType == 'zoom') { style[DeviceCapabilities.transformProperty] = slideTransformValue; var scale = 1; @@ -193,7 +195,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach scale = 1 + ((1 - distance) * 2); } style[DeviceCapabilities.transformProperty] += ' scale(' + scale + ')'; - style['transform-origin'] = '50% 50%'; + style[DeviceCapabilities.transformProperty + '-origin'] = '50% 50%'; opacity = 0; if (Math.abs(absoluteLeft) < 100) { opacity = 0.3 + distance * 0.7; @@ -226,6 +228,18 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame; + function getItemIndex(collection, target, defaultIndex) { + var result = defaultIndex; + collection.every(function(item, index) { + if (angular.equals(item, target)) { + result = index; + return false; + } + return true; + }); + return result; + }; + return { restrict: 'A', scope: true, @@ -359,6 +373,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach }; function goToSlide(index, slideOptions) { + //console.log('goToSlide', arguments); // move a to the given slide index if (index === undefined) { index = scope.carouselIndex; @@ -513,11 +528,23 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach } if (isRepeatBased) { - scope.$watchCollection(repeatCollection, function(newValue, oldValue) { - //console.log('repeatCollection', arguments); + // use rn-carousel-deep-watch to fight the Angular $watchCollection weakness : https://github.com/angular/angular.js/issues/2621 + // optional because it have some performance impacts (deep watch) + var deepWatch = (iAttributes.rnCarouselDeepWatch!==undefined); + + scope[deepWatch?'$watch':'$watchCollection'](repeatCollection, function(newValue, oldValue) { + //console.log('repeatCollection', currentSlides); + var oldSlides = (currentSlides || newValue).slice(); currentSlides = newValue; - goToSlide(scope.carouselIndex); - }); + // if deepWatch ON ,manually compare objects to guess the new position + if (deepWatch && angular.isArray(newValue)) { + var activeElement = oldValue[scope.carouselIndex]; + var newIndex = getItemIndex(newValue, activeElement, scope.carouselIndex); + goToSlide(newIndex, {animate: false}); + } else { + goToSlide(scope.carouselIndex, {animate: false}); + } + }, true); } function swipeEnd(coords, event, forceAnimation) { diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index ed33567..8e39acb 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -5,4 +5,4 @@ * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f["transform-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f["transform-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){{var k=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(l,m){var n,o,p=l[0].querySelector("li"),q=p?p.attributes:[],r=!1,s=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=q[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(n=c[1],o=c[2],n)return angular.isDefined(m.rnCarouselBuffered)&&(s=!0,b.value=n+" in "+o+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),r=!0,!1}return!0}),function(l,m,n){function p(){return m[0].querySelectorAll("ul[rn-carousel] > li")}function q(a){K=!0,z({x:a.clientX,y:a.clientY},a)}function t(a){var b=100*l.carouselBufferIndex+a;angular.forEach(p(),function(a,c){a.style.cssText=i(h(c,b,H.transitionType))})}function u(a,b){if(void 0===a&&(a=l.carouselIndex),b=b||{},b.animate===!1||"none"===H.transitionType)return N=!1,J=-100*a,l.carouselIndex=a,void A();N=!0;var c=new j;c.tween({from:{x:J},to:{x:-100*a},duration:H.transitionDuration,easing:H.transitionEasing,step:function(a){t(a.x)},finish:function(){N=!1,l.$apply(function(){l.carouselIndex=a,J=-100*a,A()})}})}function v(){var a=m[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function w(){L=v()}function x(a){return c.bind("mouseup",q),w(),M=m[0].querySelector("li").getBoundingClientRect().left,C=!0,D=a.x,!1}function y(a){if(!N){var b,c;if(C&&(b=a.x,c=D-b,c>2||-2>c)){K=!0;var d=J+100*-c/L;t(d)}return!1}}function z(a,b){if((!b||K)&&(c.unbind("mouseup",q),C=!1,K=!1,E=D-a.x,0!==E&&!N))if(J+=100*-E/L,H.isSequential){var d=H.moveTreshold*L,e=-E,f=-Math[e>=0?"ceil":"floor"](e/L),g=Math.abs(e)>d;F&&f+l.carouselIndex>=F.length&&(f=F.length-1-l.carouselIndex),f+l.carouselIndex<0&&(f=-l.carouselIndex);var h=g?f:0;E=l.carouselIndex+h,u(E)}else l.$apply(function(){l.carouselIndex=parseInt(-J/100,10),A()})}function A(){var a=0,b=(l.carouselBufferSize-1)/2;s?(a=l.carouselIndex<=b?0:F&&F.lengthF.length-l.carouselBufferSize?F.length-l.carouselBufferSize:l.carouselIndex-b,l.carouselBufferIndex=a,f(function(){t(J)},0,!1)):f(function(){t(J)},0,!1)}function B(){w(),u()}k++;var C,D,E,F,G={transitionType:n.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},H=angular.extend({},G),I=!1,J=0,K=!1,L=null,M=null,N=!1;if(void 0!==n.rnCarouselControls){var O='';m.append(e(angular.element(O))(l))}a.bind(m,{start:x,move:y,end:z,cancel:function(a){z({},a)}}),l.nextSlide=function(a){var b=l.carouselIndex+1;b>F.length-1&&(b=0),N||u(b,a)},l.prevSlide=function(a){var b=l.carouselIndex-1;0>b&&(b=F.length-1),u(b,a)};var P=!0;l.carouselIndex=0,r||(F=[],angular.forEach(p(),function(a,b){F.push({id:b})}));var Q;if(void 0!==n.rnCarouselAutoSlide){var R=parseInt(n.rnCarouselAutoSlide,10)||H.autoSlideDuration;Q=g(function(){N||C||l.nextSlide()},1e3*R)}if(n.rnCarouselIndex){var S=function(a){T.assign(l.$parent,a)},T=d(n.rnCarouselIndex);angular.isFunction(T.assign)?(l.$watch("carouselIndex",function(a){N||S(a)}),l.$parent.$watch(T,function(a){void 0!==a&&null!==a&&(F&&a>=F.length?(a=F.length-1,S(a)):F&&0>a&&(a=0,S(a)),N||u(a,{animate:!P}),P=!1)}),I=!0):isNaN(n.rnCarouselIndex)||u(parseInt(n.rnCarouselIndex,10),{animate:!1})}else u(0,{animate:!P}),P=!1;n.rnCarouselLocked&&l.$watch(n.rnCarouselLocked,function(a){N=a===!0?!0:!1}),r&&l.$watchCollection(o,function(a){F=a,u(l.carouselIndex)}),l.$on("$destroy",function(){c.unbind("mouseup",q)}),l.carouselBufferIndex=0,l.carouselBufferSize=H.bufferSize;var U=angular.element(b);U.bind("orientationchange",B),U.bind("resize",B),l.$on("$destroy",function(){c.unbind("mouseup",q),U.unbind("orientationchange",B),U.unbind("resize",B)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f[a.transformProperty+"-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f[a.transformProperty+"-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){function k(a,b,c){var d=c;return a.every(function(a,c){return angular.equals(a,b)?(d=c,!1):!0}),d}{var l=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li"),r=q?q.attributes:[],s=!1,t=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=r[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(t=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),s=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("ul[rn-carousel] > li")}function r(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b=100*m.carouselBufferIndex+a;angular.forEach(q(),function(a,c){a.style.cssText=i(h(c,b,I.transitionType))})}function v(a,b){if(void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){var a=n[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function x(){M=w()}function y(a){return c.bind("mouseup",r),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){if(!O){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}}function A(a,b){if((!b||L)&&(c.unbind("mouseup",r),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=I.moveTreshold*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;t?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}l++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,s||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;if(o.rnCarouselLocked&&m.$watch(o.rnCarouselLocked,function(a){O=a===!0?!0:!1}),s){var V=void 0!==o.rnCarouselDeepWatch;m[V?"$watch":"$watchCollection"](p,function(a,b){(G||a).slice();if(G=a,V&&angular.isArray(a)){var c=b[m.carouselIndex],d=k(a,c,m.carouselIndex);v(d,{animate:!1})}else v(m.carouselIndex,{animate:!1})},!0)}m.$on("$destroy",function(){c.unbind("mouseup",r)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var W=angular.element(b);W.bind("orientationchange",C),W.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",r),W.unbind("orientationchange",C),W.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index 8752676..0d531a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.5", + "version": "0.3.6", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { From 5b2235e0c926d089dce683dd28093150bf204b75 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Tue, 11 Nov 2014 14:30:29 +0100 Subject: [PATCH 108/159] fix(shifty): upgrade to latest version --- bower.json | 2 +- dist/angular-carousel.js | 2513 +++++++++++++++++---------------- dist/angular-carousel.min.js | 4 +- package.json | 2 +- src/directives/rn-carousel.js | 2 +- src/directives/shifty.js | 2511 ++++++++++++++++---------------- 6 files changed, 2556 insertions(+), 2478 deletions(-) diff --git a/bower.json b/bower.json index dd01b6a..3cd6d32 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.6", + "version": "0.3.7", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/dist/angular-carousel.js b/dist/angular-carousel.js index 35fa6be..905d0f5 100644 --- a/dist/angular-carousel.js +++ b/dist/angular-carousel.js @@ -1,6 +1,6 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.5 - 2014-11-06 + * @version v0.3.7 - 2014-11-11 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT @@ -238,7 +238,7 @@ angular.module('angular-carousel').run(['$templateCache', function($templateCach return true; }); return result; - }; + } return { restrict: 'A', @@ -657,1381 +657,1420 @@ angular.module('angular-carousel.shifty', []) .factory('Tweenable', function() { - (function (root, window) { - /*! - * Shifty Core - * By Jeremy Kahn - jeremyckahn@gmail.com - */ + /*! shifty - v1.3.4 - 2014-10-29 - http://jeremyckahn.github.io/shifty */ + ;(function (root) { + + /*! + * Shifty Core + * By Jeremy Kahn - jeremyckahn@gmail.com + */ + + var Tweenable = (function () { + + 'use strict'; + + // Aliases that get defined later in this function + var formula; + + // CONSTANTS + var DEFAULT_SCHEDULE_FUNCTION; + var DEFAULT_EASING = 'linear'; + var DEFAULT_DURATION = 500; + var UPDATE_TIME = 1000 / 60; + + var _now = Date.now + ? Date.now + : function () {return +new Date();}; + + var now = typeof SHIFTY_DEBUG_NOW !== 'undefined' ? SHIFTY_DEBUG_NOW : _now; + + if (typeof window !== 'undefined') { + // requestAnimationFrame() shim by Paul Irish (modified for Shifty) + // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame + || window.webkitRequestAnimationFrame + || window.oRequestAnimationFrame + || window.msRequestAnimationFrame + || (window.mozCancelRequestAnimationFrame + && window.mozRequestAnimationFrame) + || setTimeout; + } else { + DEFAULT_SCHEDULE_FUNCTION = setTimeout; + } - // UglifyJS define hack. Used for unit testing. Contents of this if are - // compiled away. - if (typeof SHIFTY_DEBUG_NOW === 'undefined') { - SHIFTY_DEBUG_NOW = function () { - return +new Date(); - }; + function noop () { + // NOOP! } - var Tweenable = (function () { - - 'use strict'; - - // Aliases that get defined later in this function - var formula; - - // CONSTANTS - var DEFAULT_SCHEDULE_FUNCTION; - var DEFAULT_EASING = 'linear'; - var DEFAULT_DURATION = 500; - var UPDATE_TIME = 1000 / 60; - - var _now = Date.now - ? Date.now - : function () {return +new Date();}; - - var now = SHIFTY_DEBUG_NOW - ? SHIFTY_DEBUG_NOW - : _now; - - if (typeof window !== 'undefined') { - // requestAnimationFrame() shim by Paul Irish (modified for Shifty) - // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame - || window.webkitRequestAnimationFrame - || window.oRequestAnimationFrame - || window.msRequestAnimationFrame - || (window.mozCancelRequestAnimationFrame - && window.mozRequestAnimationFrame) - || setTimeout; - } else { - DEFAULT_SCHEDULE_FUNCTION = setTimeout; + /*! + * Handy shortcut for doing a for-in loop. This is not a "normal" each + * function, it is optimized for Shifty. The iterator function only receives + * the property name, not the value. + * @param {Object} obj + * @param {Function(string)} fn + */ + function each (obj, fn) { + var key; + for (key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + fn(key); + } } + } - function noop () { - // NOOP! - } + /*! + * Perform a shallow copy of Object properties. + * @param {Object} targetObject The object to copy into + * @param {Object} srcObject The object to copy from + * @return {Object} A reference to the augmented `targetObj` Object + */ + function shallowCopy (targetObj, srcObj) { + each(srcObj, function (prop) { + targetObj[prop] = srcObj[prop]; + }); - /*! - * Handy shortcut for doing a for-in loop. This is not a "normal" each - * function, it is optimized for Shifty. The iterator function only receives - * the property name, not the value. - * @param {Object} obj - * @param {Function(string)} fn - */ - function each (obj, fn) { - var key; - for (key in obj) { - if (Object.hasOwnProperty.call(obj, key)) { - fn(key); - } + return targetObj; + } + + /*! + * Copies each property from src onto target, but only if the property to + * copy to target is undefined. + * @param {Object} target Missing properties in this Object are filled in + * @param {Object} src + */ + function defaults (target, src) { + each(src, function (prop) { + if (typeof target[prop] === 'undefined') { + target[prop] = src[prop]; + } + }); + } + + /*! + * Calculates the interpolated tween values of an Object for a given + * timestamp. + * @param {Number} forPosition The position to compute the state for. + * @param {Object} currentState Current state properties. + * @param {Object} originalState: The original state properties the Object is + * tweening from. + * @param {Object} targetState: The destination state properties the Object + * is tweening to. + * @param {number} duration: The length of the tween in milliseconds. + * @param {number} timestamp: The UNIX epoch time at which the tween began. + * @param {Object} easing: This Object's keys must correspond to the keys in + * targetState. + */ + function tweenProps (forPosition, currentState, originalState, targetState, + duration, timestamp, easing) { + var normalizedPosition = (forPosition - timestamp) / duration; + + var prop; + for (prop in currentState) { + if (currentState.hasOwnProperty(prop)) { + currentState[prop] = tweenProp(originalState[prop], + targetState[prop], formula[easing[prop]], normalizedPosition); } } - /*! - * Perform a shallow copy of Object properties. - * @param {Object} targetObject The object to copy into - * @param {Object} srcObject The object to copy from - * @return {Object} A reference to the augmented `targetObj` Object - */ - function shallowCopy (targetObj, srcObj) { - each(srcObj, function (prop) { - targetObj[prop] = srcObj[prop]; - }); + return currentState; + } - return targetObj; - } + /*! + * Tweens a single property. + * @param {number} start The value that the tween started from. + * @param {number} end The value that the tween should end at. + * @param {Function} easingFunc The easing curve to apply to the tween. + * @param {number} position The normalized position (between 0.0 and 1.0) to + * calculate the midpoint of 'start' and 'end' against. + * @return {number} The tweened value. + */ + function tweenProp (start, end, easingFunc, position) { + return start + (end - start) * easingFunc(position); + } - /*! - * Copies each property from src onto target, but only if the property to - * copy to target is undefined. - * @param {Object} target Missing properties in this Object are filled in - * @param {Object} src - */ - function defaults (target, src) { - each(src, function (prop) { - if (typeof target[prop] === 'undefined') { - target[prop] = src[prop]; - } - }); - } + /*! + * Applies a filter to Tweenable instance. + * @param {Tweenable} tweenable The `Tweenable` instance to call the filter + * upon. + * @param {String} filterName The name of the filter to apply. + */ + function applyFilter (tweenable, filterName) { + var filters = Tweenable.prototype.filter; + var args = tweenable._filterArgs; - /*! - * Calculates the interpolated tween values of an Object for a given - * timestamp. - * @param {Number} forPosition The position to compute the state for. - * @param {Object} currentState Current state properties. - * @param {Object} originalState: The original state properties the Object is - * tweening from. - * @param {Object} targetState: The destination state properties the Object - * is tweening to. - * @param {number} duration: The length of the tween in milliseconds. - * @param {number} timestamp: The UNIX epoch time at which the tween began. - * @param {Object} easing: This Object's keys must correspond to the keys in - * targetState. - */ - function tweenProps (forPosition, currentState, originalState, targetState, - duration, timestamp, easing) { - var normalizedPosition = (forPosition - timestamp) / duration; - - var prop; - for (prop in currentState) { - if (currentState.hasOwnProperty(prop)) { - currentState[prop] = tweenProp(originalState[prop], - targetState[prop], formula[easing[prop]], normalizedPosition); - } + each(filters, function (name) { + if (typeof filters[name][filterName] !== 'undefined') { + filters[name][filterName].apply(tweenable, args); } + }); + } - return currentState; + var timeoutHandler_endTime; + var timeoutHandler_currentTime; + var timeoutHandler_isEnded; + var timeoutHandler_offset; + /*! + * Handles the update logic for one step of a tween. + * @param {Tweenable} tweenable + * @param {number} timestamp + * @param {number} duration + * @param {Object} currentState + * @param {Object} originalState + * @param {Object} targetState + * @param {Object} easing + * @param {Function(Object, *, number)} step + * @param {Function(Function,number)}} schedule + */ + function timeoutHandler (tweenable, timestamp, duration, currentState, + originalState, targetState, easing, step, schedule) { + timeoutHandler_endTime = timestamp + duration; + timeoutHandler_currentTime = Math.min(now(), timeoutHandler_endTime); + timeoutHandler_isEnded = + timeoutHandler_currentTime >= timeoutHandler_endTime; + + timeoutHandler_offset = duration - ( + timeoutHandler_endTime - timeoutHandler_currentTime); + + if (tweenable.isPlaying() && !timeoutHandler_isEnded) { + tweenable._scheduleId = schedule(tweenable._timeoutHandler, UPDATE_TIME); + + applyFilter(tweenable, 'beforeTween'); + tweenProps(timeoutHandler_currentTime, currentState, originalState, + targetState, duration, timestamp, easing); + applyFilter(tweenable, 'afterTween'); + + step(currentState, tweenable._attachment, timeoutHandler_offset); + } else if (timeoutHandler_isEnded) { + step(targetState, tweenable._attachment, timeoutHandler_offset); + tweenable.stop(true); } + } - /*! - * Tweens a single property. - * @param {number} start The value that the tween started from. - * @param {number} end The value that the tween should end at. - * @param {Function} easingFunc The easing curve to apply to the tween. - * @param {number} position The normalized position (between 0.0 and 1.0) to - * calculate the midpoint of 'start' and 'end' against. - * @return {number} The tweened value. - */ - function tweenProp (start, end, easingFunc, position) { - return start + (end - start) * easingFunc(position); - } - /*! - * Applies a filter to Tweenable instance. - * @param {Tweenable} tweenable The `Tweenable` instance to call the filter - * upon. - * @param {String} filterName The name of the filter to apply. - */ - function applyFilter (tweenable, filterName) { - var filters = Tweenable.prototype.filter; - var args = tweenable._filterArgs; - - each(filters, function (name) { - if (typeof filters[name][filterName] !== 'undefined') { - filters[name][filterName].apply(tweenable, args); + /*! + * Creates a usable easing Object from either a string or another easing + * Object. If `easing` is an Object, then this function clones it and fills + * in the missing properties with "linear". + * @param {Object} fromTweenParams + * @param {Object|string} easing + */ + function composeEasingObject (fromTweenParams, easing) { + var composedEasing = {}; + + if (typeof easing === 'string') { + each(fromTweenParams, function (prop) { + composedEasing[prop] = easing; + }); + } else { + each(fromTweenParams, function (prop) { + if (!composedEasing[prop]) { + composedEasing[prop] = easing[prop] || DEFAULT_EASING; } }); } - var timeoutHandler_endTime; - var timeoutHandler_currentTime; - var timeoutHandler_isEnded; - /*! - * Handles the update logic for one step of a tween. - * @param {Tweenable} tweenable - * @param {number} timestamp - * @param {number} duration - * @param {Object} currentState - * @param {Object} originalState - * @param {Object} targetState - * @param {Object} easing - * @param {Function} step - * @param {Function(Function,number)}} schedule - */ - function timeoutHandler (tweenable, timestamp, duration, currentState, - originalState, targetState, easing, step, schedule) { - timeoutHandler_endTime = timestamp + duration; - timeoutHandler_currentTime = Math.min(now(), timeoutHandler_endTime); - timeoutHandler_isEnded = timeoutHandler_currentTime >= timeoutHandler_endTime; - - if (tweenable.isPlaying() && !timeoutHandler_isEnded) { - schedule(tweenable._timeoutHandler, UPDATE_TIME); - - applyFilter(tweenable, 'beforeTween'); - tweenProps(timeoutHandler_currentTime, currentState, originalState, - targetState, duration, timestamp, easing); - applyFilter(tweenable, 'afterTween'); - - step(currentState); - } else if (timeoutHandler_isEnded) { - step(targetState); - tweenable.stop(true); - } - } - - - /*! - * Creates a usable easing Object from either a string or another easing - * Object. If `easing` is an Object, then this function clones it and fills - * in the missing properties with "linear". - * @param {Object} fromTweenParams - * @param {Object|string} easing - */ - function composeEasingObject (fromTweenParams, easing) { - var composedEasing = {}; - - if (typeof easing === 'string') { - each(fromTweenParams, function (prop) { - composedEasing[prop] = easing; - }); - } else { - each(fromTweenParams, function (prop) { - if (!composedEasing[prop]) { - composedEasing[prop] = easing[prop] || DEFAULT_EASING; - } - }); - } + return composedEasing; + } - return composedEasing; + /** + * Tweenable constructor. + * @param {Object=} opt_initialState The values that the initial tween should start at if a "from" object is not provided to Tweenable#tween. + * @param {Object=} opt_config See Tweenable.prototype.setConfig() + * @constructor + */ + function Tweenable (opt_initialState, opt_config) { + this._currentState = opt_initialState || {}; + this._configured = false; + this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION; + + // To prevent unnecessary calls to setConfig do not set default configuration here. + // Only set default configuration immediately before tweening if none has been set. + if (typeof opt_config !== 'undefined') { + this.setConfig(opt_config); } + } - /** - * Tweenable constructor. - * @param {Object=} opt_initialState The values that the initial tween should start at if a "from" object is not provided to Tweenable#tween. - * @param {Object=} opt_config See Tweenable.prototype.setConfig() - * @constructor - */ - function Tweenable (opt_initialState, opt_config) { - this._currentState = opt_initialState || {}; - this._configured = false; - this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION; - - // To prevent unnecessary calls to setConfig do not set default configuration here. - // Only set default configuration immediately before tweening if none has been set. - if (typeof opt_config !== 'undefined') { - this.setConfig(opt_config); - } + /** + * Configure and start a tween. + * @param {Object=} opt_config See Tweenable.prototype.setConfig() + * @return {Tweenable} + */ + Tweenable.prototype.tween = function (opt_config) { + if (this._isTweening) { + return this; } - /** - * Configure and start a tween. - * @param {Object=} opt_config See Tweenable.prototype.setConfig() - * @return {Tweenable} - */ - Tweenable.prototype.tween = function (opt_config) { - if (this._isTweening) { - return this; - } + // Only set default config if no configuration has been set previously and none is provided now. + if (opt_config !== undefined || !this._configured) { + this.setConfig(opt_config); + } - // Only set default config if no configuration has been set previously and none is provided now. - if (opt_config !== undefined || !this._configured) { - this.setConfig(opt_config); - } + this._timestamp = now(); + this._start(this.get(), this._attachment); + return this.resume(); + }; - this._start(this.get()); - return this.resume(); - }; + /** + * Sets the tween configuration. `config` may have the following options: + * + * - __from__ (_Object=_): Starting position. If omitted, the current state is used. + * - __to__ (_Object=_): Ending position. + * - __duration__ (_number=_): How many milliseconds to animate for. + * - __start__ (_Function(Object)_): Function to execute when the tween begins. Receives the state of the tween as the first parameter. Attachment is the second parameter. + * - __step__ (_Function(Object, *, number)_): Function to execute on every tick. Receives the state of the tween as the first parameter. Attachment is the second parameter, and the time elapsed since the start of the tween is the third parameter. This function is not called on the final step of the animation, but `finish` is. + * - __finish__ (_Function(Object, *)_): Function to execute upon tween completion. Receives the state of the tween as the first parameter. Attachment is the second parameter. + * - __easing__ (_Object|string=_): Easing curve name(s) to use for the tween. + * - __attachment__ (_Object|string|any=_): Value that is attached to this instance and passed on to the step/start/finish methods. + * @param {Object} config + * @return {Tweenable} + */ + Tweenable.prototype.setConfig = function (config) { + config = config || {}; + this._configured = true; - /** - * Sets the tween configuration. `config` may have the following options: - * - * - __from__ (_Object=_): Starting position. If omitted, the current state is used. - * - __to__ (_Object=_): Ending position. - * - __duration__ (_number=_): How many milliseconds to animate for. - * - __start__ (_Function(Object)=_): Function to execute when the tween begins. Receives the state of the tween as the only parameter. - * - __step__ (_Function(Object)=_): Function to execute on every tick. Receives the state of the tween as the only parameter. This function is not called on the final step of the animation, but `finish` is. - * - __finish__ (_Function(Object)=_): Function to execute upon tween completion. Receives the state of the tween as the only parameter. - * - __easing__ (_Object|string=_): Easing curve name(s) to use for the tween. - * @param {Object} config - * @return {Tweenable} - */ - Tweenable.prototype.setConfig = function (config) { - config = config || {}; - this._configured = true; - - // Init the internal state - this._pausedAtTime = null; - this._start = config.start || noop; - this._step = config.step || noop; - this._finish = config.finish || noop; - this._duration = config.duration || DEFAULT_DURATION; - this._currentState = config.from || this.get(); - this._originalState = this.get(); - this._targetState = config.to || this.get(); - this._timestamp = now(); - - // Aliases used below - var currentState = this._currentState; - var targetState = this._targetState; - - // Ensure that there is always something to tween to. - defaults(targetState, currentState); - - this._easing = composeEasingObject( - currentState, config.easing || DEFAULT_EASING); - - this._filterArgs = - [currentState, this._originalState, targetState, this._easing]; - - applyFilter(this, 'tweenCreated'); - return this; - }; + // Attach something to this Tweenable instance (e.g.: a DOM element, an object, a string, etc.); + this._attachment = config.attachment; - /** - * Gets the current state. - * @return {Object} - */ - Tweenable.prototype.get = function () { - return shallowCopy({}, this._currentState); - }; + // Init the internal state + this._pausedAtTime = null; + this._scheduleId = null; + this._start = config.start || noop; + this._step = config.step || noop; + this._finish = config.finish || noop; + this._duration = config.duration || DEFAULT_DURATION; + this._currentState = config.from || this.get(); + this._originalState = this.get(); + this._targetState = config.to || this.get(); - /** - * Sets the current state. - * @param {Object} state - */ - Tweenable.prototype.set = function (state) { - this._currentState = state; - }; + // Aliases used below + var currentState = this._currentState; + var targetState = this._targetState; - /** - * Pauses a tween. Paused tweens can be resumed from the point at which they were paused. This is different than [`stop()`](#stop), as that method causes a tween to start over when it is resumed. - * @return {Tweenable} - */ - Tweenable.prototype.pause = function () { - this._pausedAtTime = now(); - this._isPaused = true; - return this; - }; + // Ensure that there is always something to tween to. + defaults(targetState, currentState); - /** - * Resumes a paused tween. - * @return {Tweenable} - */ - Tweenable.prototype.resume = function () { - if (this._isPaused) { - this._timestamp += now() - this._pausedAtTime; - } + this._easing = composeEasingObject( + currentState, config.easing || DEFAULT_EASING); - this._isPaused = false; - this._isTweening = true; + this._filterArgs = + [currentState, this._originalState, targetState, this._easing]; - var self = this; - this._timeoutHandler = function () { - timeoutHandler(self, self._timestamp, self._duration, self._currentState, - self._originalState, self._targetState, self._easing, self._step, - self._scheduleFunction); - }; + applyFilter(this, 'tweenCreated'); + return this; + }; - this._timeoutHandler(); + /** + * Gets the current state. + * @return {Object} + */ + Tweenable.prototype.get = function () { + return shallowCopy({}, this._currentState); + }; - return this; - }; + /** + * Sets the current state. + * @param {Object} state + */ + Tweenable.prototype.set = function (state) { + this._currentState = state; + }; - /** - * Stops and cancels a tween. - * @param {boolean=} gotoEnd If false or omitted, the tween just stops at its current state, and the "finish" handler is not invoked. If true, the tweened object's values are instantly set to the target values, and "finish" is invoked. - * @return {Tweenable} - */ - Tweenable.prototype.stop = function (gotoEnd) { - this._isTweening = false; - this._isPaused = false; - this._timeoutHandler = noop; + /** + * Pauses a tween. Paused tweens can be resumed from the point at which they were paused. This is different than [`stop()`](#stop), as that method causes a tween to start over when it is resumed. + * @return {Tweenable} + */ + Tweenable.prototype.pause = function () { + this._pausedAtTime = now(); + this._isPaused = true; + return this; + }; - if (gotoEnd) { - shallowCopy(this._currentState, this._targetState); - applyFilter(this, 'afterTweenEnd'); - this._finish.call(this, this._currentState); - } + /** + * Resumes a paused tween. + * @return {Tweenable} + */ + Tweenable.prototype.resume = function () { + if (this._isPaused) { + this._timestamp += now() - this._pausedAtTime; + } - return this; - }; + this._isPaused = false; + this._isTweening = true; - /** - * Returns whether or not a tween is running. - * @return {boolean} - */ - Tweenable.prototype.isPlaying = function () { - return this._isTweening && !this._isPaused; + var self = this; + this._timeoutHandler = function () { + timeoutHandler(self, self._timestamp, self._duration, self._currentState, + self._originalState, self._targetState, self._easing, self._step, + self._scheduleFunction); }; - /** - * Sets a custom schedule function. - * - * If a custom function is not set the default one is used [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) if available, otherwise [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)). - * - * @param {Function(Function,number)} scheduleFunction The function to be called to schedule the next frame to be rendered - */ - Tweenable.prototype.setScheduleFunction = function (scheduleFunction) { - this._scheduleFunction = scheduleFunction; - }; + this._timeoutHandler(); - /** - * `delete`s all "own" properties. Call this when the `Tweenable` instance is no longer needed to free memory. - */ - Tweenable.prototype.dispose = function () { - var prop; - for (prop in this) { - if (this.hasOwnProperty(prop)) { - delete this[prop]; - } - } - }; + return this; + }; - /*! - * Filters are used for transforming the properties of a tween at various - * points in a Tweenable's life cycle. See the README for more info on this. - */ - Tweenable.prototype.filter = {}; - - /*! - * This object contains all of the tweens available to Shifty. It is extendible - simply attach properties to the Tweenable.prototype.formula Object following the same format at linear. - * - * `pos` should be a normalized `number` (between 0 and 1). - */ - Tweenable.prototype.formula = { - linear: function (pos) { - return pos; - } - }; + /** + * Move the state of the animation to a specific point in the tween's timeline. + * If the animation is not running, this will cause the `step` handlers to be + * called. + * @param {millisecond} millisecond The millisecond of the animation to seek to. + * @return {Tweenable} + */ + Tweenable.prototype.seek = function (millisecond) { + this._timestamp = now() - millisecond; - formula = Tweenable.prototype.formula; - - shallowCopy(Tweenable, { - 'now': now - ,'each': each - ,'tweenProps': tweenProps - ,'tweenProp': tweenProp - ,'applyFilter': applyFilter - ,'shallowCopy': shallowCopy - ,'defaults': defaults - ,'composeEasingObject': composeEasingObject - }); + if (!this.isPlaying()) { + this._isTweening = true; + this._isPaused = false; - // `root` is provided in the intro/outro files. + // If the animation is not running, call timeoutHandler to make sure that + // any step handlers are run. + timeoutHandler(this, this._timestamp, this._duration, this._currentState, + this._originalState, this._targetState, this._easing, this._step, + this._scheduleFunction); - // A hook used for unit testing. - if (typeof SHIFTY_DEBUG_NOW === 'function') { - root.timeoutHandler = timeoutHandler; + this._timeoutHandler(); + this.pause(); } - // Bootstrap Tweenable appropriately for the environment. - if (typeof exports === 'object') { - // CommonJS - module.exports = Tweenable; - } else if (typeof define === 'function' && define.amd) { - // AMD - define(function () {return Tweenable;}); - } else if (typeof root.Tweenable === 'undefined') { - // Browser: Make `Tweenable` globally accessible. - root.Tweenable = Tweenable; + return this; + }; + + /** + * Stops and cancels a tween. + * @param {boolean=} gotoEnd If false or omitted, the tween just stops at its current state, and the "finish" handler is not invoked. If true, the tweened object's values are instantly set to the target values, and "finish" is invoked. + * @return {Tweenable} + */ + Tweenable.prototype.stop = function (gotoEnd) { + this._isTweening = false; + this._isPaused = false; + this._timeoutHandler = noop; + + (root.cancelAnimationFrame || + root.webkitCancelAnimationFrame || + root.oCancelAnimationFrame || + root.msCancelAnimationFrame || + root.mozCancelRequestAnimationFrame || + root.clearTimeout)(this._scheduleId); + + if (gotoEnd) { + shallowCopy(this._currentState, this._targetState); + applyFilter(this, 'afterTweenEnd'); + this._finish.call(this, this._currentState, this._attachment); } - return Tweenable; + return this; + }; - } ()); - - window.Tweenable = Tweenable; - /*! - * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). + /** + * Returns whether or not a tween is running. + * @return {boolean} + */ + Tweenable.prototype.isPlaying = function () { + return this._isTweening && !this._isPaused; + }; + + /** + * Sets a custom schedule function. * - * Based on Easing Equations (c) 2003 [Robert Penner](http://www.robertpenner.com/), all rights reserved. This work is [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html). + * If a custom function is not set the default one is used [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) if available, otherwise [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)). + * + * @param {Function(Function,number)} scheduleFunction The function to be called to schedule the next frame to be rendered */ + Tweenable.prototype.setScheduleFunction = function (scheduleFunction) { + this._scheduleFunction = scheduleFunction; + }; + + /** + * `delete`s all "own" properties. Call this when the `Tweenable` instance is no longer needed to free memory. + */ + Tweenable.prototype.dispose = function () { + var prop; + for (prop in this) { + if (this.hasOwnProperty(prop)) { + delete this[prop]; + } + } + }; /*! - * TERMS OF USE - EASING EQUATIONS - * Open source under the BSD License. - * Easing Equations (c) 2003 Robert Penner, all rights reserved. + * Filters are used for transforming the properties of a tween at various + * points in a Tweenable's life cycle. See the README for more info on this. */ + Tweenable.prototype.filter = {}; - ;(function () { - - Tweenable.shallowCopy(Tweenable.prototype.formula, { - easeInQuad: function (pos) { - return Math.pow(pos, 2); - }, - - easeOutQuad: function (pos) { - return -(Math.pow((pos - 1), 2) - 1); - }, - - easeInOutQuad: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,2);} - return -0.5 * ((pos -= 2) * pos - 2); - }, - - easeInCubic: function (pos) { - return Math.pow(pos, 3); - }, - - easeOutCubic: function (pos) { - return (Math.pow((pos - 1), 3) + 1); - }, - - easeInOutCubic: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,3);} - return 0.5 * (Math.pow((pos - 2),3) + 2); - }, - - easeInQuart: function (pos) { - return Math.pow(pos, 4); - }, - - easeOutQuart: function (pos) { - return -(Math.pow((pos - 1), 4) - 1); - }, - - easeInOutQuart: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} - return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); - }, - - easeInQuint: function (pos) { - return Math.pow(pos, 5); - }, - - easeOutQuint: function (pos) { - return (Math.pow((pos - 1), 5) + 1); - }, - - easeInOutQuint: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,5);} - return 0.5 * (Math.pow((pos - 2),5) + 2); - }, - - easeInSine: function (pos) { - return -Math.cos(pos * (Math.PI / 2)) + 1; - }, - - easeOutSine: function (pos) { - return Math.sin(pos * (Math.PI / 2)); - }, - - easeInOutSine: function (pos) { - return (-0.5 * (Math.cos(Math.PI * pos) - 1)); - }, - - easeInExpo: function (pos) { - return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1)); - }, - - easeOutExpo: function (pos) { - return (pos === 1) ? 1 : -Math.pow(2, -10 * pos) + 1; - }, - - easeInOutExpo: function (pos) { - if (pos === 0) {return 0;} - if (pos === 1) {return 1;} - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(2,10 * (pos - 1));} - return 0.5 * (-Math.pow(2, -10 * --pos) + 2); - }, - - easeInCirc: function (pos) { - return -(Math.sqrt(1 - (pos * pos)) - 1); - }, - - easeOutCirc: function (pos) { - return Math.sqrt(1 - Math.pow((pos - 1), 2)); - }, - - easeInOutCirc: function (pos) { - if ((pos /= 0.5) < 1) {return -0.5 * (Math.sqrt(1 - pos * pos) - 1);} - return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1); - }, - - easeOutBounce: function (pos) { - if ((pos) < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, - - easeInBack: function (pos) { - var s = 1.70158; - return (pos) * pos * ((s + 1) * pos - s); - }, - - easeOutBack: function (pos) { - var s = 1.70158; - return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1; - }, - - easeInOutBack: function (pos) { - var s = 1.70158; - if ((pos /= 0.5) < 1) {return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));} - return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); - }, - - elastic: function (pos) { - return -1 * Math.pow(4,-8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1; - }, - - swingFromTo: function (pos) { - var s = 1.70158; - return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) : - 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); - }, - - swingFrom: function (pos) { - var s = 1.70158; - return pos * pos * ((s + 1) * pos - s); - }, - - swingTo: function (pos) { - var s = 1.70158; - return (pos -= 1) * pos * ((s + 1) * pos + s) + 1; - }, - - bounce: function (pos) { - if (pos < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, - - bouncePast: function (pos) { - if (pos < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, + /*! + * This object contains all of the tweens available to Shifty. It is extendible - simply attach properties to the Tweenable.prototype.formula Object following the same format at linear. + * + * `pos` should be a normalized `number` (between 0 and 1). + */ + Tweenable.prototype.formula = { + linear: function (pos) { + return pos; + } + }; + + formula = Tweenable.prototype.formula; + + shallowCopy(Tweenable, { + 'now': now + ,'each': each + ,'tweenProps': tweenProps + ,'tweenProp': tweenProp + ,'applyFilter': applyFilter + ,'shallowCopy': shallowCopy + ,'defaults': defaults + ,'composeEasingObject': composeEasingObject + }); + + // `root` is provided in the intro/outro files. - easeFromTo: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} - return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); - }, + // A hook used for unit testing. + if (typeof SHIFTY_DEBUG_NOW === 'function') { + root.timeoutHandler = timeoutHandler; + } + + // Bootstrap Tweenable appropriately for the environment. + if (typeof exports === 'object') { + // CommonJS + module.exports = Tweenable; + } else if (typeof define === 'function' && define.amd) { + // AMD + define(function () {return Tweenable;}); + } else if (typeof root.Tweenable === 'undefined') { + // Browser: Make `Tweenable` globally accessible. + root.Tweenable = Tweenable; + } - easeFrom: function (pos) { - return Math.pow(pos,4); - }, + return Tweenable; - easeTo: function (pos) { - return Math.pow(pos,0.25); + } ()); + + /*! + * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). + * + * Based on Easing Equations (c) 2003 [Robert Penner](http://www.robertpenner.com/), all rights reserved. This work is [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html). + */ + + /*! + * TERMS OF USE - EASING EQUATIONS + * Open source under the BSD License. + * Easing Equations (c) 2003 Robert Penner, all rights reserved. + */ + + ;(function () { + + Tweenable.shallowCopy(Tweenable.prototype.formula, { + easeInQuad: function (pos) { + return Math.pow(pos, 2); + }, + + easeOutQuad: function (pos) { + return -(Math.pow((pos - 1), 2) - 1); + }, + + easeInOutQuad: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,2);} + return -0.5 * ((pos -= 2) * pos - 2); + }, + + easeInCubic: function (pos) { + return Math.pow(pos, 3); + }, + + easeOutCubic: function (pos) { + return (Math.pow((pos - 1), 3) + 1); + }, + + easeInOutCubic: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,3);} + return 0.5 * (Math.pow((pos - 2),3) + 2); + }, + + easeInQuart: function (pos) { + return Math.pow(pos, 4); + }, + + easeOutQuart: function (pos) { + return -(Math.pow((pos - 1), 4) - 1); + }, + + easeInOutQuart: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} + return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); + }, + + easeInQuint: function (pos) { + return Math.pow(pos, 5); + }, + + easeOutQuint: function (pos) { + return (Math.pow((pos - 1), 5) + 1); + }, + + easeInOutQuint: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,5);} + return 0.5 * (Math.pow((pos - 2),5) + 2); + }, + + easeInSine: function (pos) { + return -Math.cos(pos * (Math.PI / 2)) + 1; + }, + + easeOutSine: function (pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + + easeInOutSine: function (pos) { + return (-0.5 * (Math.cos(Math.PI * pos) - 1)); + }, + + easeInExpo: function (pos) { + return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1)); + }, + + easeOutExpo: function (pos) { + return (pos === 1) ? 1 : -Math.pow(2, -10 * pos) + 1; + }, + + easeInOutExpo: function (pos) { + if (pos === 0) {return 0;} + if (pos === 1) {return 1;} + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(2,10 * (pos - 1));} + return 0.5 * (-Math.pow(2, -10 * --pos) + 2); + }, + + easeInCirc: function (pos) { + return -(Math.sqrt(1 - (pos * pos)) - 1); + }, + + easeOutCirc: function (pos) { + return Math.sqrt(1 - Math.pow((pos - 1), 2)); + }, + + easeInOutCirc: function (pos) { + if ((pos /= 0.5) < 1) {return -0.5 * (Math.sqrt(1 - pos * pos) - 1);} + return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1); + }, + + easeOutBounce: function (pos) { + if ((pos) < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); } - }); + }, + + easeInBack: function (pos) { + var s = 1.70158; + return (pos) * pos * ((s + 1) * pos - s); + }, + + easeOutBack: function (pos) { + var s = 1.70158; + return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1; + }, + + easeInOutBack: function (pos) { + var s = 1.70158; + if ((pos /= 0.5) < 1) {return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));} + return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); + }, + + elastic: function (pos) { + return -1 * Math.pow(4,-8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1; + }, + + swingFromTo: function (pos) { + var s = 1.70158; + return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) : + 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); + }, + + swingFrom: function (pos) { + var s = 1.70158; + return pos * pos * ((s + 1) * pos - s); + }, + + swingTo: function (pos) { + var s = 1.70158; + return (pos -= 1) * pos * ((s + 1) * pos + s) + 1; + }, + + bounce: function (pos) { + if (pos < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); + } + }, + + bouncePast: function (pos) { + if (pos < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); + } + }, - }()); + easeFromTo: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} + return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); + }, - /*! - * The Bezier magic in this file is adapted/copied almost wholesale from - * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js), - * which was adapted from Apple code (which probably came from - * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)). - * Special thanks to Apple and Thomas Fuchs for much of this code. - */ + easeFrom: function (pos) { + return Math.pow(pos,4); + }, + easeTo: function (pos) { + return Math.pow(pos,0.25); + } + }); + + }()); + + /*! + * The Bezier magic in this file is adapted/copied almost wholesale from + * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js), + * which was adapted from Apple code (which probably came from + * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)). + * Special thanks to Apple and Thomas Fuchs for much of this code. + */ + + /*! + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder(s) nor the names of any + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + ;(function () { + // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/ + function cubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration) { + var ax = 0,bx = 0,cx = 0,ay = 0,by = 0,cy = 0; + function sampleCurveX(t) {return ((ax * t + bx) * t + cx) * t;} + function sampleCurveY(t) {return ((ay * t + by) * t + cy) * t;} + function sampleCurveDerivativeX(t) {return (3.0 * ax * t + 2.0 * bx) * t + cx;} + function solveEpsilon(duration) {return 1.0 / (200.0 * duration);} + function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));} + function fabs(n) {if (n >= 0) {return n;}else {return 0 - n;}} + function solveCurveX(x,epsilon) { + var t0,t1,t2,x2,d2,i; + for (t2 = x, i = 0; i < 8; i++) {x2 = sampleCurveX(t2) - x; if (fabs(x2) < epsilon) {return t2;} d2 = sampleCurveDerivativeX(t2); if (fabs(d2) < 1e-6) {break;} t2 = t2 - x2 / d2;} + t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) {return t0;} if (t2 > t1) {return t1;} + while (t0 < t1) {x2 = sampleCurveX(t2); if (fabs(x2 - x) < epsilon) {return t2;} if (x > x2) {t0 = t2;}else {t1 = t2;} t2 = (t1 - t0) * 0.5 + t0;} + return t2; // Failure. + } + cx = 3.0 * p1x; bx = 3.0 * (p2x - p1x) - cx; ax = 1.0 - cx - bx; cy = 3.0 * p1y; by = 3.0 * (p2y - p1y) - cy; ay = 1.0 - cy - by; + return solve(t, solveEpsilon(duration)); + } /*! - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * getCubicBezierTransition(x1, y1, x2, y2) -> Function * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * Generates a transition easing function that is compatible + * with WebKit's CSS transitions `-webkit-transition-timing-function` + * CSS property. * - * 3. Neither the name of the copyright holder(s) nor the names of any - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * The W3C has more information about + * + * CSS3 transition timing functions. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {function} */ - ;(function () { - // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/ - function cubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration) { - var ax = 0,bx = 0,cx = 0,ay = 0,by = 0,cy = 0; - function sampleCurveX(t) {return ((ax * t + bx) * t + cx) * t;} - function sampleCurveY(t) {return ((ay * t + by) * t + cy) * t;} - function sampleCurveDerivativeX(t) {return (3.0 * ax * t + 2.0 * bx) * t + cx;} - function solveEpsilon(duration) {return 1.0 / (200.0 * duration);} - function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));} - function fabs(n) {if (n >= 0) {return n;}else {return 0 - n;}} - function solveCurveX(x,epsilon) { - var t0,t1,t2,x2,d2,i; - for (t2 = x, i = 0; i < 8; i++) {x2 = sampleCurveX(t2) - x; if (fabs(x2) < epsilon) {return t2;} d2 = sampleCurveDerivativeX(t2); if (fabs(d2) < 1e-6) {break;} t2 = t2 - x2 / d2;} - t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) {return t0;} if (t2 > t1) {return t1;} - while (t0 < t1) {x2 = sampleCurveX(t2); if (fabs(x2 - x) < epsilon) {return t2;} if (x > x2) {t0 = t2;}else {t1 = t2;} t2 = (t1 - t0) * 0.5 + t0;} - return t2; // Failure. - } - cx = 3.0 * p1x; bx = 3.0 * (p2x - p1x) - cx; ax = 1.0 - cx - bx; cy = 3.0 * p1y; by = 3.0 * (p2y - p1y) - cy; ay = 1.0 - cy - by; - return solve(t, solveEpsilon(duration)); - } - /*! - * getCubicBezierTransition(x1, y1, x2, y2) -> Function - * - * Generates a transition easing function that is compatible - * with WebKit's CSS transitions `-webkit-transition-timing-function` - * CSS property. - * - * The W3C has more information about - * - * CSS3 transition timing functions. - * - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @return {function} - */ - function getCubicBezierTransition (x1, y1, x2, y2) { - return function (pos) { - return cubicBezierAtTime(pos,x1,y1,x2,y2,1); - }; - } - // End ported code - - /** - * Creates a Bezier easing function and attaches it to `Tweenable.prototype.formula`. This function gives you total control over the easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing the curves you can make with this function. - * - * @param {string} name The name of the easing curve. Overwrites the old easing function on Tweenable.prototype.formula if it exists. - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @return {function} The easing function that was attached to Tweenable.prototype.formula. - */ - Tweenable.setBezierFunction = function (name, x1, y1, x2, y2) { - var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2); - cubicBezierTransition.x1 = x1; - cubicBezierTransition.y1 = y1; - cubicBezierTransition.x2 = x2; - cubicBezierTransition.y2 = y2; - - return Tweenable.prototype.formula[name] = cubicBezierTransition; + function getCubicBezierTransition (x1, y1, x2, y2) { + return function (pos) { + return cubicBezierAtTime(pos,x1,y1,x2,y2,1); }; + } + // End ported code + /** + * Creates a Bezier easing function and attaches it to `Tweenable.prototype.formula`. This function gives you total control over the easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing the curves you can make with this function. + * + * @param {string} name The name of the easing curve. Overwrites the old easing function on Tweenable.prototype.formula if it exists. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {function} The easing function that was attached to Tweenable.prototype.formula. + */ + Tweenable.setBezierFunction = function (name, x1, y1, x2, y2) { + var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2); + cubicBezierTransition.x1 = x1; + cubicBezierTransition.y1 = y1; + cubicBezierTransition.x2 = x2; + cubicBezierTransition.y2 = y2; - /** - * `delete`s an easing function from `Tweenable.prototype.formula`. Be careful with this method, as it `delete`s whatever easing formula matches `name` (which means you can delete default Shifty easing functions). - * - * @param {string} name The name of the easing function to delete. - * @return {function} - */ - Tweenable.unsetBezierFunction = function (name) { - delete Tweenable.prototype.formula[name]; - }; + return Tweenable.prototype.formula[name] = cubicBezierTransition; + }; - })(); - ;(function () { + /** + * `delete`s an easing function from `Tweenable.prototype.formula`. Be careful with this method, as it `delete`s whatever easing formula matches `name` (which means you can delete default Shifty easing functions). + * + * @param {string} name The name of the easing function to delete. + * @return {function} + */ + Tweenable.unsetBezierFunction = function (name) { + delete Tweenable.prototype.formula[name]; + }; - function getInterpolatedValues ( - from, current, targetState, position, easing) { - return Tweenable.tweenProps( - position, current, from, targetState, 1, 0, easing); - } + })(); - // Fake a Tweenable and patch some internals. This approach allows us to - // skip uneccessary processing and object recreation, cutting down on garbage - // collection pauses. - var mockTweenable = new Tweenable(); - mockTweenable._filterArgs = []; - - /** - * Compute the midpoint of two Objects. This method effectively calculates a specific frame of animation that [Tweenable#tween](shifty.core.js.html#tween) does many times over the course of a tween. - * - * Example: - * - * ``` - * var interpolatedValues = Tweenable.interpolate({ - * width: '100px', - * opacity: 0, - * color: '#fff' - * }, { - * width: '200px', - * opacity: 1, - * color: '#000' - * }, 0.5); - * - * console.log(interpolatedValues); - * // {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"} - * ``` - * - * @param {Object} from The starting values to tween from. - * @param {Object} targetState The ending values to tween to. - * @param {number} position The normalized position value (between 0.0 and 1.0) to interpolate the values between `from` and `to` for. `from` represents 0 and `to` represents `1`. - * @param {string|Object} easing The easing curve(s) to calculate the midpoint against. You can reference any easing function attached to `Tweenable.prototype.formula`. If omitted, this defaults to "linear". - * @return {Object} - */ - Tweenable.interpolate = function (from, targetState, position, easing) { - var current = Tweenable.shallowCopy({}, from); - var easingObject = Tweenable.composeEasingObject( - from, easing || 'linear'); - - mockTweenable.set({}); - - // Alias and reuse the _filterArgs array instead of recreating it. - var filterArgs = mockTweenable._filterArgs; - filterArgs.length = 0; - filterArgs[0] = current; - filterArgs[1] = from; - filterArgs[2] = targetState; - filterArgs[3] = easingObject; - - // Any defined value transformation must be applied - Tweenable.applyFilter(mockTweenable, 'tweenCreated'); - Tweenable.applyFilter(mockTweenable, 'beforeTween'); - - var interpolatedValues = getInterpolatedValues( - from, current, targetState, position, easingObject); - - // Transform values back into their original format - Tweenable.applyFilter(mockTweenable, 'afterTween'); - - return interpolatedValues; - }; + ;(function () { + + function getInterpolatedValues ( + from, current, targetState, position, easing) { + return Tweenable.tweenProps( + position, current, from, targetState, 1, 0, easing); + } - }()); + // Fake a Tweenable and patch some internals. This approach allows us to + // skip uneccessary processing and object recreation, cutting down on garbage + // collection pauses. + var mockTweenable = new Tweenable(); + mockTweenable._filterArgs = []; /** - * Adds string interpolation support to Shifty. - * - * The Token extension allows Shifty to tween numbers inside of strings. Among other things, this allows you to animate CSS properties. For example, you can do this: - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(45px)'}, - * to: { transform: 'translateX(90xp)'} - * }); - * ``` - * - * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate: - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(45px)'}, - * to: { transform: 'translateX(90px)'}, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` - * - * The above snippet will log something like this in the console: - * - * ``` - * translateX(60.3px) - * ... - * translateX(76.05px) - * ... - * translateX(90px) - * ``` - * - * Another use for this is animating colors: - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { color: 'rgb(0,255,0)'}, - * to: { color: 'rgb(255,0,255)'}, - * step: function (state) { - * console.log(state.color); - * } - * }); - * ``` - * - * The above snippet will log something like this: - * - * ``` - * rgb(84,170,84) - * ... - * rgb(170,84,170) - * ... - * rgb(255,0,255) - * ``` - * - * This extension also supports hexadecimal colors, in both long (`#ff00ff`) and short (`#f0f`) forms. Be aware that hexadecimal input values will be converted into the equivalent RGB output values. This is done to optimize for performance. - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { color: '#0f0'}, - * to: { color: '#f0f'}, - * step: function (state) { - * console.log(state.color); - * } - * }); - * ``` - * - * This snippet will generate the same output as the one before it because equivalent values were supplied (just in hexadecimal form rather than RGB): - * - * ``` - * rgb(84,170,84) - * ... - * rgb(170,84,170) - * ... - * rgb(255,0,255) - * ``` - * - * ## Easing support - * - * Easing works somewhat differently in the Token extension. This is because some CSS properties have multiple values in them, and you might need to tween each value along its own easing curve. A basic example: - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(0px) translateY(0px)'}, - * to: { transform: 'translateX(100px) translateY(100px)'}, - * easing: { transform: 'easeInQuad' }, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` + * Compute the midpoint of two Objects. This method effectively calculates a specific frame of animation that [Tweenable#tween](shifty.core.js.html#tween) does many times over the course of a tween. * - * The above snippet create values like this: + * Example: * - * ``` - * translateX(11.560000000000002px) translateY(11.560000000000002px) - * ... - * translateX(46.24000000000001px) translateY(46.24000000000001px) - * ... - * translateX(100px) translateY(100px) - * ``` + * var interpolatedValues = Tweenable.interpolate({ + * width: '100px', + * opacity: 0, + * color: '#fff' + * }, { + * width: '200px', + * opacity: 1, + * color: '#000' + * }, 0.5); * - * In this case, the values for `translateX` and `translateY` are always the same for each step of the tween, because they have the same start and end points and both use the same easing curve. We can also tween `translateX` and `translateY` along independent curves: + * console.log(interpolatedValues); + * // {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"} * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(0px) translateY(0px)'}, - * to: { transform: 'translateX(100px) translateY(100px)'}, - * easing: { transform: 'easeInQuad bounce' }, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` - * - * The above snippet create values like this: - * - * ``` - * translateX(10.89px) translateY(82.355625px) - * ... - * translateX(44.89000000000001px) translateY(86.73062500000002px) - * ... - * translateX(100px) translateY(100px) - * ``` - * - * `translateX` and `translateY` are not in sync anymore, because `easeInQuad` was specified for `translateX` and `bounce` for `translateY`. Mixing and matching easing curves can make for some interesting motion in your animations. - * - * The order of the space-separated easing curves correspond the token values they apply to. If there are more token values than easing curves listed, the last easing curve listed is used. + * @param {Object} from The starting values to tween from. + * @param {Object} targetState The ending values to tween to. + * @param {number} position The normalized position value (between 0.0 and 1.0) to interpolate the values between `from` and `to` for. `from` represents 0 and `to` represents `1`. + * @param {string|Object} easing The easing curve(s) to calculate the midpoint against. You can reference any easing function attached to `Tweenable.prototype.formula`. If omitted, this defaults to "linear". + * @return {Object} */ - function token () { - // Functionality for this extension runs implicitly if it is loaded. - } /*!*/ - - // token function is defined above only so that dox-foundation sees it as - // documentation and renders it. It is never used, and is optimized away at - // build time. - - ;(function (Tweenable) { - - /*! - * @typedef {{ - * formatString: string - * chunkNames: Array. - * }} - */ - var formatManifest; - - // CONSTANTS - - var R_NUMBER_COMPONENT = /(\d|\-|\.)/; - var R_FORMAT_CHUNKS = /([^\-0-9\.]+)/g; - var R_UNFORMATTED_VALUES = /[0-9.\-]+/g; - var R_RGB = new RegExp( - 'rgb\\(' + R_UNFORMATTED_VALUES.source + - (/,\s*/.source) + R_UNFORMATTED_VALUES.source + - (/,\s*/.source) + R_UNFORMATTED_VALUES.source + '\\)', 'g'); - var R_RGB_PREFIX = /^.*\(/; - var R_HEX = /#([0-9]|[a-f]){3,6}/gi; - var VALUE_PLACEHOLDER = 'VAL'; - - // HELPERS - - var getFormatChunksFrom_accumulator = []; - /*! - * @param {Array.number} rawValues - * @param {string} prefix - * - * @return {Array.} - */ - function getFormatChunksFrom (rawValues, prefix) { - getFormatChunksFrom_accumulator.length = 0; + Tweenable.interpolate = function (from, targetState, position, easing) { + var current = Tweenable.shallowCopy({}, from); + var easingObject = Tweenable.composeEasingObject( + from, easing || 'linear'); + + mockTweenable.set({}); + + // Alias and reuse the _filterArgs array instead of recreating it. + var filterArgs = mockTweenable._filterArgs; + filterArgs.length = 0; + filterArgs[0] = current; + filterArgs[1] = from; + filterArgs[2] = targetState; + filterArgs[3] = easingObject; + + // Any defined value transformation must be applied + Tweenable.applyFilter(mockTweenable, 'tweenCreated'); + Tweenable.applyFilter(mockTweenable, 'beforeTween'); + + var interpolatedValues = getInterpolatedValues( + from, current, targetState, position, easingObject); + + // Transform values back into their original format + Tweenable.applyFilter(mockTweenable, 'afterTween'); + + return interpolatedValues; + }; + + }()); + + /** + * Adds string interpolation support to Shifty. + * + * The Token extension allows Shifty to tween numbers inside of strings. Among + * other things, this allows you to animate CSS properties. For example, you + * can do this: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(45px)'}, + * to: { transform: 'translateX(90xp)'} + * }); + * + * ` ` + * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(45px)'}, + * to: { transform: 'translateX(90px)'}, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet will log something like this in the console: + * + * translateX(60.3px) + * ... + * translateX(76.05px) + * ... + * translateX(90px) + * + * ` ` + * Another use for this is animating colors: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { color: 'rgb(0,255,0)'}, + * to: { color: 'rgb(255,0,255)'}, + * step: function (state) { + * console.log(state.color); + * } + * }); + * + * ` ` + * The above snippet will log something like this: + * + * rgb(84,170,84) + * ... + * rgb(170,84,170) + * ... + * rgb(255,0,255) + * + * ` ` + * This extension also supports hexadecimal colors, in both long (`#ff00ff`) + * and short (`#f0f`) forms. Be aware that hexadecimal input values will be + * converted into the equivalent RGB output values. This is done to optimize + * for performance. + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { color: '#0f0'}, + * to: { color: '#f0f'}, + * step: function (state) { + * console.log(state.color); + * } + * }); + * + * ` ` + * This snippet will generate the same output as the one before it because + * equivalent values were supplied (just in hexadecimal form rather than RGB): + * + * rgb(84,170,84) + * ... + * rgb(170,84,170) + * ... + * rgb(255,0,255) + * + * ` ` + * ` ` + * ## Easing support + * + * Easing works somewhat differently in the Token extension. This is because + * some CSS properties have multiple values in them, and you might need to + * tween each value along its own easing curve. A basic example: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(0px) translateY(0px)'}, + * to: { transform: 'translateX(100px) translateY(100px)'}, + * easing: { transform: 'easeInQuad' }, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet create values like this: + * + * translateX(11.560000000000002px) translateY(11.560000000000002px) + * ... + * translateX(46.24000000000001px) translateY(46.24000000000001px) + * ... + * translateX(100px) translateY(100px) + * + * ` ` + * In this case, the values for `translateX` and `translateY` are always the + * same for each step of the tween, because they have the same start and end + * points and both use the same easing curve. We can also tween `translateX` + * and `translateY` along independent curves: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(0px) translateY(0px)'}, + * to: { transform: 'translateX(100px) translateY(100px)'}, + * easing: { transform: 'easeInQuad bounce' }, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet create values like this: + * + * translateX(10.89px) translateY(82.355625px) + * ... + * translateX(44.89000000000001px) translateY(86.73062500000002px) + * ... + * translateX(100px) translateY(100px) + * + * ` ` + * `translateX` and `translateY` are not in sync anymore, because `easeInQuad` + * was specified for `translateX` and `bounce` for `translateY`. Mixing and + * matching easing curves can make for some interesting motion in your + * animations. + * + * The order of the space-separated easing curves correspond the token values + * they apply to. If there are more token values than easing curves listed, + * the last easing curve listed is used. + */ + function token () { + // Functionality for this extension runs implicitly if it is loaded. + } /*!*/ + + // token function is defined above only so that dox-foundation sees it as + // documentation and renders it. It is never used, and is optimized away at + // build time. + + ;(function (Tweenable) { - var rawValuesLength = rawValues.length; - var i; + /*! + * @typedef {{ + * formatString: string + * chunkNames: Array. + * }} + */ + var formatManifest; - for (i = 0; i < rawValuesLength; i++) { - getFormatChunksFrom_accumulator.push('_' + prefix + '_' + i); - } + // CONSTANTS - return getFormatChunksFrom_accumulator; - } + var R_NUMBER_COMPONENT = /(\d|\-|\.)/; + var R_FORMAT_CHUNKS = /([^\-0-9\.]+)/g; + var R_UNFORMATTED_VALUES = /[0-9.\-]+/g; + var R_RGB = new RegExp( + 'rgb\\(' + R_UNFORMATTED_VALUES.source + + (/,\s*/.source) + R_UNFORMATTED_VALUES.source + + (/,\s*/.source) + R_UNFORMATTED_VALUES.source + '\\)', 'g'); + var R_RGB_PREFIX = /^.*\(/; + var R_HEX = /#([0-9]|[a-f]){3,6}/gi; + var VALUE_PLACEHOLDER = 'VAL'; - /*! - * @param {string} formattedString - * - * @return {string} - */ - function getFormatStringFrom (formattedString) { - var chunks = formattedString.match(R_FORMAT_CHUNKS); - - if (!chunks) { - // chunks will be null if there were no tokens to parse in - // formattedString (for example, if formattedString is '2'). Coerce - // chunks to be useful here. - chunks = ['', '']; - - // If there is only one chunk, assume that the string is a number - // followed by a token... - // NOTE: This may be an unwise assumption. - } else if (chunks.length === 1 || - // ...or if the string starts with a number component (".", "-", or a - // digit)... - formattedString[0].match(R_NUMBER_COMPONENT)) { - // ...prepend an empty string here to make sure that the formatted number - // is properly replaced by VALUE_PLACEHOLDER - chunks.unshift(''); - } + // HELPERS - return chunks.join(VALUE_PLACEHOLDER); - } + var getFormatChunksFrom_accumulator = []; + /*! + * @param {Array.number} rawValues + * @param {string} prefix + * + * @return {Array.} + */ + function getFormatChunksFrom (rawValues, prefix) { + getFormatChunksFrom_accumulator.length = 0; - /*! - * Convert all hex color values within a string to an rgb string. - * - * @param {Object} stateObject - * - * @return {Object} The modified obj - */ - function sanitizeObjectForHexProps (stateObject) { - Tweenable.each(stateObject, function (prop) { - var currentProp = stateObject[prop]; - - if (typeof currentProp === 'string' && currentProp.match(R_HEX)) { - stateObject[prop] = sanitizeHexChunksToRGB(currentProp); - } - }); - } + var rawValuesLength = rawValues.length; + var i; - /*! - * @param {string} str - * - * @return {string} - */ - function sanitizeHexChunksToRGB (str) { - return filterStringChunks(R_HEX, str, convertHexToRGB); + for (i = 0; i < rawValuesLength; i++) { + getFormatChunksFrom_accumulator.push('_' + prefix + '_' + i); } - /*! - * @param {string} hexString - * - * @return {string} - */ - function convertHexToRGB (hexString) { - var rgbArr = hexToRGBArray(hexString); - return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')'; + return getFormatChunksFrom_accumulator; + } + + /*! + * @param {string} formattedString + * + * @return {string} + */ + function getFormatStringFrom (formattedString) { + var chunks = formattedString.match(R_FORMAT_CHUNKS); + + if (!chunks) { + // chunks will be null if there were no tokens to parse in + // formattedString (for example, if formattedString is '2'). Coerce + // chunks to be useful here. + chunks = ['', '']; + + // If there is only one chunk, assume that the string is a number + // followed by a token... + // NOTE: This may be an unwise assumption. + } else if (chunks.length === 1 || + // ...or if the string starts with a number component (".", "-", or a + // digit)... + formattedString[0].match(R_NUMBER_COMPONENT)) { + // ...prepend an empty string here to make sure that the formatted number + // is properly replaced by VALUE_PLACEHOLDER + chunks.unshift(''); } - var hexToRGBArray_returnArray = []; - /*! - * Convert a hexadecimal string to an array with three items, one each for - * the red, blue, and green decimal values. - * - * @param {string} hex A hexadecimal string. - * - * @returns {Array.} The converted Array of RGB values if `hex` is a - * valid string, or an Array of three 0's. - */ - function hexToRGBArray (hex) { - - hex = hex.replace(/#/, ''); - - // If the string is a shorthand three digit hex notation, normalize it to - // the standard six digit notation - if (hex.length === 3) { - hex = hex.split(''); - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + return chunks.join(VALUE_PLACEHOLDER); + } + + /*! + * Convert all hex color values within a string to an rgb string. + * + * @param {Object} stateObject + * + * @return {Object} The modified obj + */ + function sanitizeObjectForHexProps (stateObject) { + Tweenable.each(stateObject, function (prop) { + var currentProp = stateObject[prop]; + + if (typeof currentProp === 'string' && currentProp.match(R_HEX)) { + stateObject[prop] = sanitizeHexChunksToRGB(currentProp); } + }); + } - hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2)); - hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2)); - hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2)); + /*! + * @param {string} str + * + * @return {string} + */ + function sanitizeHexChunksToRGB (str) { + return filterStringChunks(R_HEX, str, convertHexToRGB); + } - return hexToRGBArray_returnArray; - } + /*! + * @param {string} hexString + * + * @return {string} + */ + function convertHexToRGB (hexString) { + var rgbArr = hexToRGBArray(hexString); + return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')'; + } - /*! - * Convert a base-16 number to base-10. - * - * @param {Number|String} hex The value to convert - * - * @returns {Number} The base-10 equivalent of `hex`. - */ - function hexToDec (hex) { - return parseInt(hex, 16); - } + var hexToRGBArray_returnArray = []; + /*! + * Convert a hexadecimal string to an array with three items, one each for + * the red, blue, and green decimal values. + * + * @param {string} hex A hexadecimal string. + * + * @returns {Array.} The converted Array of RGB values if `hex` is a + * valid string, or an Array of three 0's. + */ + function hexToRGBArray (hex) { - /*! - * Runs a filter operation on all chunks of a string that match a RegExp - * - * @param {RegExp} pattern - * @param {string} unfilteredString - * @param {function(string)} filter - * - * @return {string} - */ - function filterStringChunks (pattern, unfilteredString, filter) { - var pattenMatches = unfilteredString.match(pattern); - var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER); - - if (pattenMatches) { - var pattenMatchesLength = pattenMatches.length; - var currentChunk; - - for (var i = 0; i < pattenMatchesLength; i++) { - currentChunk = pattenMatches.shift(); - filteredString = filteredString.replace( - VALUE_PLACEHOLDER, filter(currentChunk)); - } - } + hex = hex.replace(/#/, ''); - return filteredString; + // If the string is a shorthand three digit hex notation, normalize it to + // the standard six digit notation + if (hex.length === 3) { + hex = hex.split(''); + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } - /*! - * Check for floating point values within rgb strings and rounds them. - * - * @param {string} formattedString - * - * @return {string} - */ - function sanitizeRGBChunks (formattedString) { - return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk); - } + hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2)); + hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2)); + hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2)); - /*! - * @param {string} rgbChunk - * - * @return {string} - */ - function sanitizeRGBChunk (rgbChunk) { - var numbers = rgbChunk.match(R_UNFORMATTED_VALUES); - var numbersLength = numbers.length; - var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0]; - - for (var i = 0; i < numbersLength; i++) { - sanitizedString += parseInt(numbers[i], 10) + ','; - } + return hexToRGBArray_returnArray; + } - sanitizedString = sanitizedString.slice(0, -1) + ')'; + /*! + * Convert a base-16 number to base-10. + * + * @param {Number|String} hex The value to convert + * + * @returns {Number} The base-10 equivalent of `hex`. + */ + function hexToDec (hex) { + return parseInt(hex, 16); + } - return sanitizedString; + /*! + * Runs a filter operation on all chunks of a string that match a RegExp + * + * @param {RegExp} pattern + * @param {string} unfilteredString + * @param {function(string)} filter + * + * @return {string} + */ + function filterStringChunks (pattern, unfilteredString, filter) { + var pattenMatches = unfilteredString.match(pattern); + var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER); + + if (pattenMatches) { + var pattenMatchesLength = pattenMatches.length; + var currentChunk; + + for (var i = 0; i < pattenMatchesLength; i++) { + currentChunk = pattenMatches.shift(); + filteredString = filteredString.replace( + VALUE_PLACEHOLDER, filter(currentChunk)); + } } - /*! - * @param {Object} stateObject - * - * @return {Object} An Object of formatManifests that correspond to - * the string properties of stateObject - */ - function getFormatManifests (stateObject) { - var manifestAccumulator = {}; - - Tweenable.each(stateObject, function (prop) { - var currentProp = stateObject[prop]; + return filteredString; + } - if (typeof currentProp === 'string') { - var rawValues = getValuesFrom(currentProp); + /*! + * Check for floating point values within rgb strings and rounds them. + * + * @param {string} formattedString + * + * @return {string} + */ + function sanitizeRGBChunks (formattedString) { + return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk); + } - manifestAccumulator[prop] = { - 'formatString': getFormatStringFrom(currentProp) - ,'chunkNames': getFormatChunksFrom(rawValues, prop) - }; - } - }); + /*! + * @param {string} rgbChunk + * + * @return {string} + */ + function sanitizeRGBChunk (rgbChunk) { + var numbers = rgbChunk.match(R_UNFORMATTED_VALUES); + var numbersLength = numbers.length; + var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0]; - return manifestAccumulator; + for (var i = 0; i < numbersLength; i++) { + sanitizedString += parseInt(numbers[i], 10) + ','; } - /*! - * @param {Object} stateObject - * @param {Object} formatManifests - */ - function expandFormattedProperties (stateObject, formatManifests) { - Tweenable.each(formatManifests, function (prop) { - var currentProp = stateObject[prop]; - var rawValues = getValuesFrom(currentProp); - var rawValuesLength = rawValues.length; - - for (var i = 0; i < rawValuesLength; i++) { - stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i]; - } + sanitizedString = sanitizedString.slice(0, -1) + ')'; - delete stateObject[prop]; - }); - } + return sanitizedString; + } - /*! - * @param {Object} stateObject - * @param {Object} formatManifests - */ - function collapseFormattedProperties (stateObject, formatManifests) { - Tweenable.each(formatManifests, function (prop) { - var currentProp = stateObject[prop]; - var formatChunks = extractPropertyChunks( - stateObject, formatManifests[prop].chunkNames); - var valuesList = getValuesList( - formatChunks, formatManifests[prop].chunkNames); - currentProp = getFormattedValues( - formatManifests[prop].formatString, valuesList); - stateObject[prop] = sanitizeRGBChunks(currentProp); - }); - } + /*! + * @param {Object} stateObject + * + * @return {Object} An Object of formatManifests that correspond to + * the string properties of stateObject + */ + function getFormatManifests (stateObject) { + var manifestAccumulator = {}; - /*! - * @param {Object} stateObject - * @param {Array.} chunkNames - * - * @return {Object} The extracted value chunks. - */ - function extractPropertyChunks (stateObject, chunkNames) { - var extractedValues = {}; - var currentChunkName, chunkNamesLength = chunkNames.length; - - for (var i = 0; i < chunkNamesLength; i++) { - currentChunkName = chunkNames[i]; - extractedValues[currentChunkName] = stateObject[currentChunkName]; - delete stateObject[currentChunkName]; - } + Tweenable.each(stateObject, function (prop) { + var currentProp = stateObject[prop]; - return extractedValues; - } + if (typeof currentProp === 'string') { + var rawValues = getValuesFrom(currentProp); - var getValuesList_accumulator = []; - /*! - * @param {Object} stateObject - * @param {Array.} chunkNames - * - * @return {Array.} - */ - function getValuesList (stateObject, chunkNames) { - getValuesList_accumulator.length = 0; - var chunkNamesLength = chunkNames.length; - - for (var i = 0; i < chunkNamesLength; i++) { - getValuesList_accumulator.push(stateObject[chunkNames[i]]); + manifestAccumulator[prop] = { + 'formatString': getFormatStringFrom(currentProp) + ,'chunkNames': getFormatChunksFrom(rawValues, prop) + }; } + }); - return getValuesList_accumulator; - } + return manifestAccumulator; + } - /*! - * @param {string} formatString - * @param {Array.} rawValues - * - * @return {string} - */ - function getFormattedValues (formatString, rawValues) { - var formattedValueString = formatString; + /*! + * @param {Object} stateObject + * @param {Object} formatManifests + */ + function expandFormattedProperties (stateObject, formatManifests) { + Tweenable.each(formatManifests, function (prop) { + var currentProp = stateObject[prop]; + var rawValues = getValuesFrom(currentProp); var rawValuesLength = rawValues.length; for (var i = 0; i < rawValuesLength; i++) { - formattedValueString = formattedValueString.replace( - VALUE_PLACEHOLDER, +rawValues[i].toFixed(4)); + stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i]; } - return formattedValueString; - } + delete stateObject[prop]; + }); + } + + /*! + * @param {Object} stateObject + * @param {Object} formatManifests + */ + function collapseFormattedProperties (stateObject, formatManifests) { + Tweenable.each(formatManifests, function (prop) { + var currentProp = stateObject[prop]; + var formatChunks = extractPropertyChunks( + stateObject, formatManifests[prop].chunkNames); + var valuesList = getValuesList( + formatChunks, formatManifests[prop].chunkNames); + currentProp = getFormattedValues( + formatManifests[prop].formatString, valuesList); + stateObject[prop] = sanitizeRGBChunks(currentProp); + }); + } - /*! - * Note: It's the duty of the caller to convert the Array elements of the - * return value into numbers. This is a performance optimization. - * - * @param {string} formattedString - * - * @return {Array.|null} - */ - function getValuesFrom (formattedString) { - return formattedString.match(R_UNFORMATTED_VALUES); + /*! + * @param {Object} stateObject + * @param {Array.} chunkNames + * + * @return {Object} The extracted value chunks. + */ + function extractPropertyChunks (stateObject, chunkNames) { + var extractedValues = {}; + var currentChunkName, chunkNamesLength = chunkNames.length; + + for (var i = 0; i < chunkNamesLength; i++) { + currentChunkName = chunkNames[i]; + extractedValues[currentChunkName] = stateObject[currentChunkName]; + delete stateObject[currentChunkName]; } - /*! - * @param {Object} easingObject - * @param {Object} tokenData - */ - function expandEasingObject (easingObject, tokenData) { - Tweenable.each(tokenData, function (prop) { - var currentProp = tokenData[prop]; - var chunkNames = currentProp.chunkNames; - var chunkLength = chunkNames.length; - var easingChunks = easingObject[prop].split(' '); - var lastEasingChunk = easingChunks[easingChunks.length - 1]; - - for (var i = 0; i < chunkLength; i++) { - easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk; - } + return extractedValues; + } - delete easingObject[prop]; - }); + var getValuesList_accumulator = []; + /*! + * @param {Object} stateObject + * @param {Array.} chunkNames + * + * @return {Array.} + */ + function getValuesList (stateObject, chunkNames) { + getValuesList_accumulator.length = 0; + var chunkNamesLength = chunkNames.length; + + for (var i = 0; i < chunkNamesLength; i++) { + getValuesList_accumulator.push(stateObject[chunkNames[i]]); } - /*! - * @param {Object} easingObject - * @param {Object} tokenData - */ - function collapseEasingObject (easingObject, tokenData) { - Tweenable.each(tokenData, function (prop) { - var currentProp = tokenData[prop]; - var chunkNames = currentProp.chunkNames; - var chunkLength = chunkNames.length; - var composedEasingString = ''; - - for (var i = 0; i < chunkLength; i++) { - composedEasingString += ' ' + easingObject[chunkNames[i]]; - delete easingObject[chunkNames[i]]; - } + return getValuesList_accumulator; + } - easingObject[prop] = composedEasingString.substr(1); - }); + /*! + * @param {string} formatString + * @param {Array.} rawValues + * + * @return {string} + */ + function getFormattedValues (formatString, rawValues) { + var formattedValueString = formatString; + var rawValuesLength = rawValues.length; + + for (var i = 0; i < rawValuesLength; i++) { + formattedValueString = formattedValueString.replace( + VALUE_PLACEHOLDER, +rawValues[i].toFixed(4)); } - Tweenable.prototype.filter.token = { - 'tweenCreated': function (currentState, fromState, toState, easingObject) { - sanitizeObjectForHexProps(currentState); - sanitizeObjectForHexProps(fromState); - sanitizeObjectForHexProps(toState); - this._tokenData = getFormatManifests(currentState); - }, - - 'beforeTween': function (currentState, fromState, toState, easingObject) { - expandEasingObject(easingObject, this._tokenData); - expandFormattedProperties(currentState, this._tokenData); - expandFormattedProperties(fromState, this._tokenData); - expandFormattedProperties(toState, this._tokenData); - }, - - 'afterTween': function (currentState, fromState, toState, easingObject) { - collapseFormattedProperties(currentState, this._tokenData); - collapseFormattedProperties(fromState, this._tokenData); - collapseFormattedProperties(toState, this._tokenData); - collapseEasingObject(easingObject, this._tokenData); + return formattedValueString; + } + + /*! + * Note: It's the duty of the caller to convert the Array elements of the + * return value into numbers. This is a performance optimization. + * + * @param {string} formattedString + * + * @return {Array.|null} + */ + function getValuesFrom (formattedString) { + return formattedString.match(R_UNFORMATTED_VALUES); + } + + /*! + * @param {Object} easingObject + * @param {Object} tokenData + */ + function expandEasingObject (easingObject, tokenData) { + Tweenable.each(tokenData, function (prop) { + var currentProp = tokenData[prop]; + var chunkNames = currentProp.chunkNames; + var chunkLength = chunkNames.length; + var easingChunks = easingObject[prop].split(' '); + var lastEasingChunk = easingChunks[easingChunks.length - 1]; + + for (var i = 0; i < chunkLength; i++) { + easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk; } - }; - } (Tweenable)); + delete easingObject[prop]; + }); + } + + /*! + * @param {Object} easingObject + * @param {Object} tokenData + */ + function collapseEasingObject (easingObject, tokenData) { + Tweenable.each(tokenData, function (prop) { + var currentProp = tokenData[prop]; + var chunkNames = currentProp.chunkNames; + var chunkLength = chunkNames.length; + var composedEasingString = ''; + + for (var i = 0; i < chunkLength; i++) { + composedEasingString += ' ' + easingObject[chunkNames[i]]; + delete easingObject[chunkNames[i]]; + } + + easingObject[prop] = composedEasingString.substr(1); + }); + } + + Tweenable.prototype.filter.token = { + 'tweenCreated': function (currentState, fromState, toState, easingObject) { + sanitizeObjectForHexProps(currentState); + sanitizeObjectForHexProps(fromState); + sanitizeObjectForHexProps(toState); + this._tokenData = getFormatManifests(currentState); + }, + + 'beforeTween': function (currentState, fromState, toState, easingObject) { + expandEasingObject(easingObject, this._tokenData); + expandFormattedProperties(currentState, this._tokenData); + expandFormattedProperties(fromState, this._tokenData); + expandFormattedProperties(toState, this._tokenData); + }, + + 'afterTween': function (currentState, fromState, toState, easingObject) { + collapseFormattedProperties(currentState, this._tokenData); + collapseFormattedProperties(fromState, this._tokenData); + collapseFormattedProperties(toState, this._tokenData); + collapseEasingObject(easingObject, this._tokenData); + } + }; + + } (Tweenable)); - }(this, window)); + }(window)); return window.Tweenable; }); diff --git a/dist/angular-carousel.min.js b/dist/angular-carousel.min.js index 8e39acb..6eb7c2a 100644 --- a/dist/angular-carousel.min.js +++ b/dist/angular-carousel.min.js @@ -1,8 +1,8 @@ /** * Angular Carousel - Mobile friendly touch carousel for AngularJS - * @version v0.3.5 - 2014-11-06 + * @version v0.3.7 - 2014-11-11 * @link http://revolunet.github.com/angular-carousel * @author Julien Bouquillon * @license MIT License, http://www.opensource.org/licenses/MIT */ -angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f[a.transformProperty+"-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f[a.transformProperty+"-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){function k(a,b,c){var d=c;return a.every(function(a,c){return angular.equals(a,b)?(d=c,!1):!0}),d}{var l=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li"),r=q?q.attributes:[],s=!1,t=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=r[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(t=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),s=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("ul[rn-carousel] > li")}function r(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b=100*m.carouselBufferIndex+a;angular.forEach(q(),function(a,c){a.style.cssText=i(h(c,b,I.transitionType))})}function v(a,b){if(void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){var a=n[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function x(){M=w()}function y(a){return c.bind("mouseup",r),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){if(!O){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}}function A(a,b){if((!b||L)&&(c.unbind("mouseup",r),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=I.moveTreshold*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;t?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}l++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,s||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;if(o.rnCarouselLocked&&m.$watch(o.rnCarouselLocked,function(a){O=a===!0?!0:!1}),s){var V=void 0!==o.rnCarouselDeepWatch;m[V?"$watch":"$watchCollection"](p,function(a,b){(G||a).slice();if(G=a,V&&angular.isArray(a)){var c=b[m.carouselIndex],d=k(a,c,m.carouselIndex);v(d,{animate:!1})}else v(m.carouselIndex,{animate:!1})},!0)}m.$on("$destroy",function(){c.unbind("mouseup",r)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var W=angular.element(b);W.bind("orientationchange",C),W.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",r),W.unbind("orientationchange",C),W.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a,b){"undefined"==typeof SHIFTY_DEBUG_NOW&&(SHIFTY_DEBUG_NOW=function(){return+new Date});var c=function(){"use strict";function c(){}function d(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function e(a,b){return d(b,function(c){a[c]=b[c]}),a}function f(a,b){d(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function g(a,b,c,d,e,f,g){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=h(c[i],d[i],m[g[i]],j));return b}function h(a,b,c,d){return a+(b-a)*c(d)}function i(a,b){var c=l.prototype.filter,e=a._filterArgs;d(c,function(d){"undefined"!=typeof c[d][b]&&c[d][b].apply(a,e)})}function j(a,b,c,d,e,f,h,j,k){t=b+c,u=Math.min(s(),t),v=u>=t,a.isPlaying()&&!v?(k(a._timeoutHandler,q),i(a,"beforeTween"),g(u,d,e,f,c,b,h),i(a,"afterTween"),j(d)):v&&(j(f),a.stop(!0))}function k(a,b){var c={};return"string"==typeof b?d(a,function(a){c[a]=b}):d(a,function(a){c[a]||(c[a]=b[a]||o)}),c}function l(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=n,"undefined"!=typeof b&&this.setConfig(b)}var m,n,o="linear",p=500,q=1e3/60,r=Date.now?Date.now:function(){return+new Date},s=SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:r;n="undefined"!=typeof b?b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||b.mozCancelRequestAnimationFrame&&b.mozRequestAnimationFrame||setTimeout:setTimeout;var t,u,v;return l.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._start(this.get()),this.resume())},l.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._pausedAtTime=null,this._start=a.start||c,this._step=a.step||c,this._finish=a.finish||c,this._duration=a.duration||p,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get(),this._timestamp=s();var b=this._currentState,d=this._targetState;return f(d,b),this._easing=k(b,a.easing||o),this._filterArgs=[b,this._originalState,d,this._easing],i(this,"tweenCreated"),this},l.prototype.get=function(){return e({},this._currentState)},l.prototype.set=function(a){this._currentState=a},l.prototype.pause=function(){return this._pausedAtTime=s(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=s()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){j(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},l.prototype.stop=function(a){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=c,a&&(e(this._currentState,this._targetState),i(this,"afterTweenEnd"),this._finish.call(this,this._currentState)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},l.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},l.prototype.filter={},l.prototype.formula={linear:function(a){return a}},m=l.prototype.formula,e(l,{now:s,each:d,tweenProps:g,tweenProp:h,applyFilter:i,shallowCopy:e,defaults:f,composeEasingObject:k}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=j),"object"==typeof exports?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):"undefined"==typeof a.Tweenable&&(a.Tweenable=l),l}();b.Tweenable=c,function(){c.shallowCopy(c.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function b(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}c.setBezierFunction=function(a,d,e,f,g){var h=b(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,c.prototype.formula[a]=h},c.unsetBezierFunction=function(a){delete c.prototype.formula[a]}}(),function(){function a(a,b,d,e,f){return c.tweenProps(e,b,a,d,1,0,f)}var b=new c;b._filterArgs=[],c.interpolate=function(d,e,f,g){var h=c.shallowCopy({},d),i=c.composeEasingObject(d,g||"linear");b.set({});var j=b._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,c.applyFilter(b,"tweenCreated"),c.applyFilter(b,"beforeTween");var k=a(d,h,e,f,i);return c.applyFilter(b,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(c)}(this,window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file +angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$timeout",function(a){return{restrict:"A",link:function(b,c,d){var e=Math.round(1e3*parseFloat(d.rnCarouselAutoSlide)),f=increment=!1,g=c.children().length;b.carouselExposedIndex||(b.carouselExposedIndex=0),stopAutoplay=function(){angular.isDefined(f)&&a.cancel(f),f=void 0},increment=function(){b.carouselExposedIndex=b.carouselExposedIndex\n')}]),function(){"use strict";angular.module("angular-carousel").service("DeviceCapabilities",function(){function a(){var a="transform",b="webkitTransform";return"undefined"!=typeof document.body.style[a]?["webkit","moz","o","ms"].every(function(b){var c="-"+b+"-transform";return"undefined"!=typeof document.body.style[c]?(a=c,!1):!0}):a="undefined"!=typeof document.body.style[b]?"-webkit-transform":void 0,a}function b(){var a,b=document.createElement("p"),c={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"};document.body.insertBefore(b,null);for(var d in c)void 0!==b.style[d]&&(b.style[d]="translate3d(1px,1px,1px)",a=window.getComputedStyle(b).getPropertyValue(c[d]));return document.body.removeChild(b),void 0!==a&&a.length>0&&"none"!==a}return{has3d:b(),transformProperty:a()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(a){return function(b,c,d){var e,f={display:"inline-block"},g=100*b+c,h=a.has3d?"translate3d("+g+"%, 0, 0)":"translate3d("+g+"%, 0)",i=(100-Math.abs(g))/100;if(a.transformProperty)if("fadeAndSlide"==d)f[a.transformProperty]=h,e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e;else if("hexagon"==d){var j=100,k=0,l=60*(i-1);j=-100*b>c?100:0,k=-100*b>c?l:-l,f[a.transformProperty]=h+" rotateY("+k+"deg)",f[a.transformProperty+"-origin"]=j+"% 50%"}else if("zoom"==d){f[a.transformProperty]=h;var m=1;Math.abs(g)<100&&(m=1+2*(1-i)),f[a.transformProperty]+=" scale("+m+")",f[a.transformProperty+"-origin"]="50% 50%",e=0,Math.abs(g)<100&&(e=.3+.7*i),f.opacity=e}else f[a.transformProperty]=h;else f["margin-left"]=g+"%";return f}}]).service("createStyleString",function(){return function(a){var b=[];return angular.forEach(a,function(a,c){b.push(c+":"+a)}),b.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable",function(a,b,c,d,e,f,g,h,i,j){function k(a,b,c){var d=c;return a.every(function(a,c){return angular.equals(a,b)?(d=c,!1):!0}),d}{var l=0;b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame}return{restrict:"A",scope:!0,compile:function(m,n){var o,p,q=m[0].querySelector("li"),r=q?q.attributes:[],s=!1,t=!1;return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(a){var b=r[a];if(angular.isDefined(b)){var c=b.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),d=c[3];if(o=c[1],p=c[2],o)return angular.isDefined(n.rnCarouselBuffered)&&(t=!0,b.value=o+" in "+p+"|carouselSlice:carouselBufferIndex:carouselBufferSize",d&&(b.value+=" track by "+d)),s=!0,!1}return!0}),function(m,n,o){function q(){return n[0].querySelectorAll("ul[rn-carousel] > li")}function r(a){L=!0,A({x:a.clientX,y:a.clientY},a)}function u(a){var b=100*m.carouselBufferIndex+a;angular.forEach(q(),function(a,c){a.style.cssText=i(h(c,b,I.transitionType))})}function v(a,b){if(void 0===a&&(a=m.carouselIndex),b=b||{},b.animate===!1||"none"===I.transitionType)return O=!1,K=-100*a,m.carouselIndex=a,B(),void 0;O=!0;var c=new j;c.tween({from:{x:K},to:{x:-100*a},duration:I.transitionDuration,easing:I.transitionEasing,step:function(a){u(a.x)},finish:function(){O=!1,m.$apply(function(){m.carouselIndex=a,K=-100*a,B()})}})}function w(){var a=n[0].getBoundingClientRect();return a.width?a.width:a.right-a.left}function x(){M=w()}function y(a){return c.bind("mouseup",r),x(),N=n[0].querySelector("li").getBoundingClientRect().left,D=!0,E=a.x,!1}function z(a){if(!O){var b,c;if(D&&(b=a.x,c=E-b,c>2||-2>c)){L=!0;var d=K+100*-c/M;u(d)}return!1}}function A(a,b){if((!b||L)&&(c.unbind("mouseup",r),D=!1,L=!1,F=E-a.x,0!==F&&!O))if(K+=100*-F/M,I.isSequential){var d=I.moveTreshold*M,e=-F,f=-Math[e>=0?"ceil":"floor"](e/M),g=Math.abs(e)>d;G&&f+m.carouselIndex>=G.length&&(f=G.length-1-m.carouselIndex),f+m.carouselIndex<0&&(f=-m.carouselIndex);var h=g?f:0;F=m.carouselIndex+h,v(F)}else m.$apply(function(){m.carouselIndex=parseInt(-K/100,10),B()})}function B(){var a=0,b=(m.carouselBufferSize-1)/2;t?(a=m.carouselIndex<=b?0:G&&G.lengthG.length-m.carouselBufferSize?G.length-m.carouselBufferSize:m.carouselIndex-b,m.carouselBufferIndex=a,f(function(){u(K)},0,!1)):f(function(){u(K)},0,!1)}function C(){x(),v()}l++;var D,E,F,G,H={transitionType:o.rnCarouselTransition||"slide",transitionEasing:"easeTo",transitionDuration:300,isSequential:!0,autoSlideDuration:3,bufferSize:5,moveTreshold:.1},I=angular.extend({},H),J=!1,K=0,L=!1,M=null,N=null,O=!1;if(void 0!==o.rnCarouselControls){var P='';n.append(e(angular.element(P))(m))}a.bind(n,{start:y,move:z,end:A,cancel:function(a){A({},a)}}),m.nextSlide=function(a){var b=m.carouselIndex+1;b>G.length-1&&(b=0),O||v(b,a)},m.prevSlide=function(a){var b=m.carouselIndex-1;0>b&&(b=G.length-1),v(b,a)};var Q=!0;m.carouselIndex=0,s||(G=[],angular.forEach(q(),function(a,b){G.push({id:b})}));var R;if(void 0!==o.rnCarouselAutoSlide){var S=parseInt(o.rnCarouselAutoSlide,10)||I.autoSlideDuration;R=g(function(){O||D||m.nextSlide()},1e3*S)}if(o.rnCarouselIndex){var T=function(a){U.assign(m.$parent,a)},U=d(o.rnCarouselIndex);angular.isFunction(U.assign)?(m.$watch("carouselIndex",function(a){O||T(a)}),m.$parent.$watch(U,function(a){void 0!==a&&null!==a&&(G&&a>=G.length?(a=G.length-1,T(a)):G&&0>a&&(a=0,T(a)),O||v(a,{animate:!Q}),Q=!1)}),J=!0):isNaN(o.rnCarouselIndex)||v(parseInt(o.rnCarouselIndex,10),{animate:!1})}else v(0,{animate:!Q}),Q=!1;if(o.rnCarouselLocked&&m.$watch(o.rnCarouselLocked,function(a){O=a===!0?!0:!1}),s){var V=void 0!==o.rnCarouselDeepWatch;m[V?"$watch":"$watchCollection"](p,function(a,b){(G||a).slice();if(G=a,V&&angular.isArray(a)){var c=b[m.carouselIndex],d=k(a,c,m.carouselIndex);v(d,{animate:!1})}else v(m.carouselIndex,{animate:!1})},!0)}m.$on("$destroy",function(){c.unbind("mouseup",r)}),m.carouselBufferIndex=0,m.carouselBufferSize=I.bufferSize;var W=angular.element(b);W.bind("orientationchange",C),W.bind("resize",C),m.$on("$destroy",function(){c.unbind("mouseup",r),W.unbind("orientationchange",C),W.unbind("resize",C)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(a){var b=function(){"use strict";function b(){}function c(a,b){var c;for(c in a)Object.hasOwnProperty.call(a,c)&&b(c)}function d(a,b){return c(b,function(c){a[c]=b[c]}),a}function e(a,b){c(b,function(c){"undefined"==typeof a[c]&&(a[c]=b[c])})}function f(a,b,c,d,e,f,h){var i,j=(a-f)/e;for(i in b)b.hasOwnProperty(i)&&(b[i]=g(c[i],d[i],l[h[i]],j));return b}function g(a,b,c,d){return a+(b-a)*c(d)}function h(a,b){var d=k.prototype.filter,e=a._filterArgs;c(d,function(c){"undefined"!=typeof d[c][b]&&d[c][b].apply(a,e)})}function i(a,b,c,d,e,g,i,j,k){s=b+c,t=Math.min(r(),s),u=t>=s,v=c-(s-t),a.isPlaying()&&!u?(a._scheduleId=k(a._timeoutHandler,p),h(a,"beforeTween"),f(t,d,e,g,c,b,i),h(a,"afterTween"),j(d,a._attachment,v)):u&&(j(g,a._attachment,v),a.stop(!0))}function j(a,b){var d={};return"string"==typeof b?c(a,function(a){d[a]=b}):c(a,function(a){d[a]||(d[a]=b[a]||n)}),d}function k(a,b){this._currentState=a||{},this._configured=!1,this._scheduleFunction=m,"undefined"!=typeof b&&this.setConfig(b)}var l,m,n="linear",o=500,p=1e3/60,q=Date.now?Date.now:function(){return+new Date},r="undefined"!=typeof SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:q;m="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var s,t,u,v;return k.prototype.tween=function(a){return this._isTweening?this:(void 0===a&&this._configured||this.setConfig(a),this._timestamp=r(),this._start(this.get(),this._attachment),this.resume())},k.prototype.setConfig=function(a){a=a||{},this._configured=!0,this._attachment=a.attachment,this._pausedAtTime=null,this._scheduleId=null,this._start=a.start||b,this._step=a.step||b,this._finish=a.finish||b,this._duration=a.duration||o,this._currentState=a.from||this.get(),this._originalState=this.get(),this._targetState=a.to||this.get();var c=this._currentState,d=this._targetState;return e(d,c),this._easing=j(c,a.easing||n),this._filterArgs=[c,this._originalState,d,this._easing],h(this,"tweenCreated"),this},k.prototype.get=function(){return d({},this._currentState)},k.prototype.set=function(a){this._currentState=a},k.prototype.pause=function(){return this._pausedAtTime=r(),this._isPaused=!0,this},k.prototype.resume=function(){this._isPaused&&(this._timestamp+=r()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0;var a=this;return this._timeoutHandler=function(){i(a,a._timestamp,a._duration,a._currentState,a._originalState,a._targetState,a._easing,a._step,a._scheduleFunction)},this._timeoutHandler(),this},k.prototype.seek=function(a){return this._timestamp=r()-a,this.isPlaying()||(this._isTweening=!0,this._isPaused=!1,i(this,this._timestamp,this._duration,this._currentState,this._originalState,this._targetState,this._easing,this._step,this._scheduleFunction),this._timeoutHandler(),this.pause()),this},k.prototype.stop=function(c){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=b,(a.cancelAnimationFrame||a.webkitCancelAnimationFrame||a.oCancelAnimationFrame||a.msCancelAnimationFrame||a.mozCancelRequestAnimationFrame||a.clearTimeout)(this._scheduleId),c&&(d(this._currentState,this._targetState),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState,this._attachment)),this},k.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},k.prototype.setScheduleFunction=function(a){this._scheduleFunction=a},k.prototype.dispose=function(){var a;for(a in this)this.hasOwnProperty(a)&&delete this[a]},k.prototype.filter={},k.prototype.formula={linear:function(a){return a}},l=k.prototype.formula,d(k,{now:r,each:c,tweenProps:f,tweenProp:g,applyFilter:h,shallowCopy:d,defaults:e,composeEasingObject:j}),"function"==typeof SHIFTY_DEBUG_NOW&&(a.timeoutHandler=i),"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):"undefined"==typeof a.Tweenable&&(a.Tweenable=k),k}();!function(){b.shallowCopy(b.prototype.formula,{easeInQuad:function(a){return Math.pow(a,2)},easeOutQuad:function(a){return-(Math.pow(a-1,2)-1)},easeInOutQuad:function(a){return(a/=.5)<1?.5*Math.pow(a,2):-.5*((a-=2)*a-2)},easeInCubic:function(a){return Math.pow(a,3)},easeOutCubic:function(a){return Math.pow(a-1,3)+1},easeInOutCubic:function(a){return(a/=.5)<1?.5*Math.pow(a,3):.5*(Math.pow(a-2,3)+2)},easeInQuart:function(a){return Math.pow(a,4)},easeOutQuart:function(a){return-(Math.pow(a-1,4)-1)},easeInOutQuart:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeInQuint:function(a){return Math.pow(a,5)},easeOutQuint:function(a){return Math.pow(a-1,5)+1},easeInOutQuint:function(a){return(a/=.5)<1?.5*Math.pow(a,5):.5*(Math.pow(a-2,5)+2)},easeInSine:function(a){return-Math.cos(a*(Math.PI/2))+1},easeOutSine:function(a){return Math.sin(a*(Math.PI/2))},easeInOutSine:function(a){return-.5*(Math.cos(Math.PI*a)-1)},easeInExpo:function(a){return 0===a?0:Math.pow(2,10*(a-1))},easeOutExpo:function(a){return 1===a?1:-Math.pow(2,-10*a)+1},easeInOutExpo:function(a){return 0===a?0:1===a?1:(a/=.5)<1?.5*Math.pow(2,10*(a-1)):.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return-(Math.sqrt(1-a*a)-1)},easeOutCirc:function(a){return Math.sqrt(1-Math.pow(a-1,2))},easeInOutCirc:function(a){return(a/=.5)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},easeOutBounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},easeInBack:function(a){var b=1.70158;return a*a*((b+1)*a-b)},easeOutBack:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},easeInOutBack:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},elastic:function(a){return-1*Math.pow(4,-8*a)*Math.sin(2*(6*a-1)*Math.PI/2)+1},swingFromTo:function(a){var b=1.70158;return(a/=.5)<1?.5*a*a*(((b*=1.525)+1)*a-b):.5*((a-=2)*a*(((b*=1.525)+1)*a+b)+2)},swingFrom:function(a){var b=1.70158;return a*a*((b+1)*a-b)},swingTo:function(a){var b=1.70158;return(a-=1)*a*((b+1)*a+b)+1},bounce:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},bouncePast:function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?2-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?2-(7.5625*(a-=2.25/2.75)*a+.9375):2-(7.5625*(a-=2.625/2.75)*a+.984375)},easeFromTo:function(a){return(a/=.5)<1?.5*Math.pow(a,4):-.5*((a-=2)*Math.pow(a,3)-2)},easeFrom:function(a){return Math.pow(a,4)},easeTo:function(a){return Math.pow(a,.25)}})}(),function(){function a(a,b,c,d,e,f){function g(a){return((n*a+o)*a+p)*a}function h(a){return((q*a+r)*a+s)*a}function i(a){return(3*n*a+2*o)*a+p}function j(a){return 1/(200*a)}function k(a,b){return h(m(a,b))}function l(a){return a>=0?a:0-a}function m(a,b){var c,d,e,f,h,j;for(e=a,j=0;8>j;j++){if(f=g(e)-a,l(f)e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),l(f-a)f?c=e:d=e,e=.5*(d-c)+c}return e}var n=0,o=0,p=0,q=0,r=0,s=0;return p=3*b,o=3*(d-b)-p,n=1-p-o,s=3*c,r=3*(e-c)-s,q=1-s-r,k(a,j(f))}function c(b,c,d,e){return function(f){return a(f,b,c,d,e,1)}}b.setBezierFunction=function(a,d,e,f,g){var h=c(d,e,f,g);return h.x1=d,h.y1=e,h.x2=f,h.y2=g,b.prototype.formula[a]=h},b.unsetBezierFunction=function(a){delete b.prototype.formula[a]}}(),function(){function a(a,c,d,e,f){return b.tweenProps(e,c,a,d,1,0,f)}var c=new b;c._filterArgs=[],b.interpolate=function(d,e,f,g){var h=b.shallowCopy({},d),i=b.composeEasingObject(d,g||"linear");c.set({});var j=c._filterArgs;j.length=0,j[0]=h,j[1]=d,j[2]=e,j[3]=i,b.applyFilter(c,"tweenCreated"),b.applyFilter(c,"beforeTween");var k=a(d,h,e,f,i);return b.applyFilter(c,"afterTween"),k}}(),function(a){function b(a,b){B.length=0;var c,d=a.length;for(c=0;d>c;c++)B.push("_"+b+"_"+c);return B}function c(a){var b=a.match(v);return b?(1===b.length||a[0].match(u))&&b.unshift(""):b=["",""],b.join(A)}function d(b){a.each(b,function(a){var c=b[a];"string"==typeof c&&c.match(z)&&(b[a]=e(c))})}function e(a){return i(z,a,f)}function f(a){var b=g(a);return"rgb("+b[0]+","+b[1]+","+b[2]+")"}function g(a){return a=a.replace(/#/,""),3===a.length&&(a=a.split(""),a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),C[0]=h(a.substr(0,2)),C[1]=h(a.substr(2,2)),C[2]=h(a.substr(4,2)),C}function h(a){return parseInt(a,16)}function i(a,b,c){var d=b.match(a),e=b.replace(a,A);if(d)for(var f,g=d.length,h=0;g>h;h++)f=d.shift(),e=e.replace(A,c(f));return e}function j(a){return i(x,a,k)}function k(a){for(var b=a.match(w),c=b.length,d=a.match(y)[0],e=0;c>e;e++)d+=parseInt(b[e],10)+",";return d=d.slice(0,-1)+")"}function l(d){var e={};return a.each(d,function(a){var f=d[a];if("string"==typeof f){var g=r(f);e[a]={formatString:c(f),chunkNames:b(g,a)}}}),e}function m(b,c){a.each(c,function(a){for(var d=b[a],e=r(d),f=e.length,g=0;f>g;g++)b[c[a].chunkNames[g]]=+e[g];delete b[a]})}function n(b,c){a.each(c,function(a){var d=b[a],e=o(b,c[a].chunkNames),f=p(e,c[a].chunkNames);d=q(c[a].formatString,f),b[a]=j(d)})}function o(a,b){for(var c,d={},e=b.length,f=0;e>f;f++)c=b[f],d[c]=a[c],delete a[c];return d}function p(a,b){D.length=0;for(var c=b.length,d=0;c>d;d++)D.push(a[b[d]]);return D}function q(a,b){for(var c=a,d=b.length,e=0;d>e;e++)c=c.replace(A,+b[e].toFixed(4));return c}function r(a){return a.match(w)}function s(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g=b[a].split(" "),h=g[g.length-1],i=0;f>i;i++)b[e[i]]=g[i]||h;delete b[a]})}function t(b,c){a.each(c,function(a){for(var d=c[a],e=d.chunkNames,f=e.length,g="",h=0;f>h;h++)g+=" "+b[e[h]],delete b[e[h]];b[a]=g.substr(1)})}var u=/(\d|\-|\.)/,v=/([^\-0-9\.]+)/g,w=/[0-9.\-]+/g,x=new RegExp("rgb\\("+w.source+/,\s*/.source+w.source+/,\s*/.source+w.source+"\\)","g"),y=/^.*\(/,z=/#([0-9]|[a-f]){3,6}/gi,A="VAL",B=[],C=[],D=[];a.prototype.filter.token={tweenCreated:function(a,b,c){d(a),d(b),d(c),this._tokenData=l(a)},beforeTween:function(a,b,c,d){s(d,this._tokenData),m(a,this._tokenData),m(b,this._tokenData),m(c,this._tokenData)},afterTween:function(a,b,c,d){n(a,this._tokenData),n(b,this._tokenData),n(c,this._tokenData),t(d,this._tokenData)}}}(b)}(window),window.Tweenable}),function(){"use strict";angular.module("angular-carousel").filter("carouselSlice",function(){return function(a,b,c){return angular.isArray(a)?a.slice(b,b+c):angular.isObject(a)?a:void 0}})}(); \ No newline at end of file diff --git a/package.json b/package.json index 0d531a0..3a3d624 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-carousel", "description": "Angular Carousel - Mobile friendly touch carousel for AngularJS", - "version": "0.3.6", + "version": "0.3.7", "homepage": "http://revolunet.github.com/angular-carousel", "author": "Julien Bouquillon ", "repository": { diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 84c756c..86d15a6 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -138,7 +138,7 @@ return true; }); return result; - }; + } return { restrict: 'A', diff --git a/src/directives/shifty.js b/src/directives/shifty.js index c327e38..ccb73ac 100644 --- a/src/directives/shifty.js +++ b/src/directives/shifty.js @@ -4,1381 +4,1420 @@ angular.module('angular-carousel.shifty', []) .factory('Tweenable', function() { - (function (root, window) { - /*! - * Shifty Core - * By Jeremy Kahn - jeremyckahn@gmail.com - */ + /*! shifty - v1.3.4 - 2014-10-29 - http://jeremyckahn.github.io/shifty */ + ;(function (root) { + + /*! + * Shifty Core + * By Jeremy Kahn - jeremyckahn@gmail.com + */ + + var Tweenable = (function () { + + 'use strict'; + + // Aliases that get defined later in this function + var formula; + + // CONSTANTS + var DEFAULT_SCHEDULE_FUNCTION; + var DEFAULT_EASING = 'linear'; + var DEFAULT_DURATION = 500; + var UPDATE_TIME = 1000 / 60; + + var _now = Date.now + ? Date.now + : function () {return +new Date();}; + + var now = typeof SHIFTY_DEBUG_NOW !== 'undefined' ? SHIFTY_DEBUG_NOW : _now; + + if (typeof window !== 'undefined') { + // requestAnimationFrame() shim by Paul Irish (modified for Shifty) + // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame + || window.webkitRequestAnimationFrame + || window.oRequestAnimationFrame + || window.msRequestAnimationFrame + || (window.mozCancelRequestAnimationFrame + && window.mozRequestAnimationFrame) + || setTimeout; + } else { + DEFAULT_SCHEDULE_FUNCTION = setTimeout; + } - // UglifyJS define hack. Used for unit testing. Contents of this if are - // compiled away. - if (typeof SHIFTY_DEBUG_NOW === 'undefined') { - SHIFTY_DEBUG_NOW = function () { - return +new Date(); - }; + function noop () { + // NOOP! } - var Tweenable = (function () { - - 'use strict'; - - // Aliases that get defined later in this function - var formula; - - // CONSTANTS - var DEFAULT_SCHEDULE_FUNCTION; - var DEFAULT_EASING = 'linear'; - var DEFAULT_DURATION = 500; - var UPDATE_TIME = 1000 / 60; - - var _now = Date.now - ? Date.now - : function () {return +new Date();}; - - var now = SHIFTY_DEBUG_NOW - ? SHIFTY_DEBUG_NOW - : _now; - - if (typeof window !== 'undefined') { - // requestAnimationFrame() shim by Paul Irish (modified for Shifty) - // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame - || window.webkitRequestAnimationFrame - || window.oRequestAnimationFrame - || window.msRequestAnimationFrame - || (window.mozCancelRequestAnimationFrame - && window.mozRequestAnimationFrame) - || setTimeout; - } else { - DEFAULT_SCHEDULE_FUNCTION = setTimeout; + /*! + * Handy shortcut for doing a for-in loop. This is not a "normal" each + * function, it is optimized for Shifty. The iterator function only receives + * the property name, not the value. + * @param {Object} obj + * @param {Function(string)} fn + */ + function each (obj, fn) { + var key; + for (key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + fn(key); + } } + } - function noop () { - // NOOP! - } + /*! + * Perform a shallow copy of Object properties. + * @param {Object} targetObject The object to copy into + * @param {Object} srcObject The object to copy from + * @return {Object} A reference to the augmented `targetObj` Object + */ + function shallowCopy (targetObj, srcObj) { + each(srcObj, function (prop) { + targetObj[prop] = srcObj[prop]; + }); - /*! - * Handy shortcut for doing a for-in loop. This is not a "normal" each - * function, it is optimized for Shifty. The iterator function only receives - * the property name, not the value. - * @param {Object} obj - * @param {Function(string)} fn - */ - function each (obj, fn) { - var key; - for (key in obj) { - if (Object.hasOwnProperty.call(obj, key)) { - fn(key); - } + return targetObj; + } + + /*! + * Copies each property from src onto target, but only if the property to + * copy to target is undefined. + * @param {Object} target Missing properties in this Object are filled in + * @param {Object} src + */ + function defaults (target, src) { + each(src, function (prop) { + if (typeof target[prop] === 'undefined') { + target[prop] = src[prop]; + } + }); + } + + /*! + * Calculates the interpolated tween values of an Object for a given + * timestamp. + * @param {Number} forPosition The position to compute the state for. + * @param {Object} currentState Current state properties. + * @param {Object} originalState: The original state properties the Object is + * tweening from. + * @param {Object} targetState: The destination state properties the Object + * is tweening to. + * @param {number} duration: The length of the tween in milliseconds. + * @param {number} timestamp: The UNIX epoch time at which the tween began. + * @param {Object} easing: This Object's keys must correspond to the keys in + * targetState. + */ + function tweenProps (forPosition, currentState, originalState, targetState, + duration, timestamp, easing) { + var normalizedPosition = (forPosition - timestamp) / duration; + + var prop; + for (prop in currentState) { + if (currentState.hasOwnProperty(prop)) { + currentState[prop] = tweenProp(originalState[prop], + targetState[prop], formula[easing[prop]], normalizedPosition); } } - /*! - * Perform a shallow copy of Object properties. - * @param {Object} targetObject The object to copy into - * @param {Object} srcObject The object to copy from - * @return {Object} A reference to the augmented `targetObj` Object - */ - function shallowCopy (targetObj, srcObj) { - each(srcObj, function (prop) { - targetObj[prop] = srcObj[prop]; - }); + return currentState; + } - return targetObj; - } + /*! + * Tweens a single property. + * @param {number} start The value that the tween started from. + * @param {number} end The value that the tween should end at. + * @param {Function} easingFunc The easing curve to apply to the tween. + * @param {number} position The normalized position (between 0.0 and 1.0) to + * calculate the midpoint of 'start' and 'end' against. + * @return {number} The tweened value. + */ + function tweenProp (start, end, easingFunc, position) { + return start + (end - start) * easingFunc(position); + } - /*! - * Copies each property from src onto target, but only if the property to - * copy to target is undefined. - * @param {Object} target Missing properties in this Object are filled in - * @param {Object} src - */ - function defaults (target, src) { - each(src, function (prop) { - if (typeof target[prop] === 'undefined') { - target[prop] = src[prop]; - } - }); - } + /*! + * Applies a filter to Tweenable instance. + * @param {Tweenable} tweenable The `Tweenable` instance to call the filter + * upon. + * @param {String} filterName The name of the filter to apply. + */ + function applyFilter (tweenable, filterName) { + var filters = Tweenable.prototype.filter; + var args = tweenable._filterArgs; - /*! - * Calculates the interpolated tween values of an Object for a given - * timestamp. - * @param {Number} forPosition The position to compute the state for. - * @param {Object} currentState Current state properties. - * @param {Object} originalState: The original state properties the Object is - * tweening from. - * @param {Object} targetState: The destination state properties the Object - * is tweening to. - * @param {number} duration: The length of the tween in milliseconds. - * @param {number} timestamp: The UNIX epoch time at which the tween began. - * @param {Object} easing: This Object's keys must correspond to the keys in - * targetState. - */ - function tweenProps (forPosition, currentState, originalState, targetState, - duration, timestamp, easing) { - var normalizedPosition = (forPosition - timestamp) / duration; - - var prop; - for (prop in currentState) { - if (currentState.hasOwnProperty(prop)) { - currentState[prop] = tweenProp(originalState[prop], - targetState[prop], formula[easing[prop]], normalizedPosition); - } + each(filters, function (name) { + if (typeof filters[name][filterName] !== 'undefined') { + filters[name][filterName].apply(tweenable, args); } + }); + } - return currentState; + var timeoutHandler_endTime; + var timeoutHandler_currentTime; + var timeoutHandler_isEnded; + var timeoutHandler_offset; + /*! + * Handles the update logic for one step of a tween. + * @param {Tweenable} tweenable + * @param {number} timestamp + * @param {number} duration + * @param {Object} currentState + * @param {Object} originalState + * @param {Object} targetState + * @param {Object} easing + * @param {Function(Object, *, number)} step + * @param {Function(Function,number)}} schedule + */ + function timeoutHandler (tweenable, timestamp, duration, currentState, + originalState, targetState, easing, step, schedule) { + timeoutHandler_endTime = timestamp + duration; + timeoutHandler_currentTime = Math.min(now(), timeoutHandler_endTime); + timeoutHandler_isEnded = + timeoutHandler_currentTime >= timeoutHandler_endTime; + + timeoutHandler_offset = duration - ( + timeoutHandler_endTime - timeoutHandler_currentTime); + + if (tweenable.isPlaying() && !timeoutHandler_isEnded) { + tweenable._scheduleId = schedule(tweenable._timeoutHandler, UPDATE_TIME); + + applyFilter(tweenable, 'beforeTween'); + tweenProps(timeoutHandler_currentTime, currentState, originalState, + targetState, duration, timestamp, easing); + applyFilter(tweenable, 'afterTween'); + + step(currentState, tweenable._attachment, timeoutHandler_offset); + } else if (timeoutHandler_isEnded) { + step(targetState, tweenable._attachment, timeoutHandler_offset); + tweenable.stop(true); } + } - /*! - * Tweens a single property. - * @param {number} start The value that the tween started from. - * @param {number} end The value that the tween should end at. - * @param {Function} easingFunc The easing curve to apply to the tween. - * @param {number} position The normalized position (between 0.0 and 1.0) to - * calculate the midpoint of 'start' and 'end' against. - * @return {number} The tweened value. - */ - function tweenProp (start, end, easingFunc, position) { - return start + (end - start) * easingFunc(position); - } - /*! - * Applies a filter to Tweenable instance. - * @param {Tweenable} tweenable The `Tweenable` instance to call the filter - * upon. - * @param {String} filterName The name of the filter to apply. - */ - function applyFilter (tweenable, filterName) { - var filters = Tweenable.prototype.filter; - var args = tweenable._filterArgs; - - each(filters, function (name) { - if (typeof filters[name][filterName] !== 'undefined') { - filters[name][filterName].apply(tweenable, args); + /*! + * Creates a usable easing Object from either a string or another easing + * Object. If `easing` is an Object, then this function clones it and fills + * in the missing properties with "linear". + * @param {Object} fromTweenParams + * @param {Object|string} easing + */ + function composeEasingObject (fromTweenParams, easing) { + var composedEasing = {}; + + if (typeof easing === 'string') { + each(fromTweenParams, function (prop) { + composedEasing[prop] = easing; + }); + } else { + each(fromTweenParams, function (prop) { + if (!composedEasing[prop]) { + composedEasing[prop] = easing[prop] || DEFAULT_EASING; } }); } - var timeoutHandler_endTime; - var timeoutHandler_currentTime; - var timeoutHandler_isEnded; - /*! - * Handles the update logic for one step of a tween. - * @param {Tweenable} tweenable - * @param {number} timestamp - * @param {number} duration - * @param {Object} currentState - * @param {Object} originalState - * @param {Object} targetState - * @param {Object} easing - * @param {Function} step - * @param {Function(Function,number)}} schedule - */ - function timeoutHandler (tweenable, timestamp, duration, currentState, - originalState, targetState, easing, step, schedule) { - timeoutHandler_endTime = timestamp + duration; - timeoutHandler_currentTime = Math.min(now(), timeoutHandler_endTime); - timeoutHandler_isEnded = timeoutHandler_currentTime >= timeoutHandler_endTime; - - if (tweenable.isPlaying() && !timeoutHandler_isEnded) { - schedule(tweenable._timeoutHandler, UPDATE_TIME); - - applyFilter(tweenable, 'beforeTween'); - tweenProps(timeoutHandler_currentTime, currentState, originalState, - targetState, duration, timestamp, easing); - applyFilter(tweenable, 'afterTween'); - - step(currentState); - } else if (timeoutHandler_isEnded) { - step(targetState); - tweenable.stop(true); - } - } - - - /*! - * Creates a usable easing Object from either a string or another easing - * Object. If `easing` is an Object, then this function clones it and fills - * in the missing properties with "linear". - * @param {Object} fromTweenParams - * @param {Object|string} easing - */ - function composeEasingObject (fromTweenParams, easing) { - var composedEasing = {}; - - if (typeof easing === 'string') { - each(fromTweenParams, function (prop) { - composedEasing[prop] = easing; - }); - } else { - each(fromTweenParams, function (prop) { - if (!composedEasing[prop]) { - composedEasing[prop] = easing[prop] || DEFAULT_EASING; - } - }); - } + return composedEasing; + } - return composedEasing; + /** + * Tweenable constructor. + * @param {Object=} opt_initialState The values that the initial tween should start at if a "from" object is not provided to Tweenable#tween. + * @param {Object=} opt_config See Tweenable.prototype.setConfig() + * @constructor + */ + function Tweenable (opt_initialState, opt_config) { + this._currentState = opt_initialState || {}; + this._configured = false; + this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION; + + // To prevent unnecessary calls to setConfig do not set default configuration here. + // Only set default configuration immediately before tweening if none has been set. + if (typeof opt_config !== 'undefined') { + this.setConfig(opt_config); } + } - /** - * Tweenable constructor. - * @param {Object=} opt_initialState The values that the initial tween should start at if a "from" object is not provided to Tweenable#tween. - * @param {Object=} opt_config See Tweenable.prototype.setConfig() - * @constructor - */ - function Tweenable (opt_initialState, opt_config) { - this._currentState = opt_initialState || {}; - this._configured = false; - this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION; - - // To prevent unnecessary calls to setConfig do not set default configuration here. - // Only set default configuration immediately before tweening if none has been set. - if (typeof opt_config !== 'undefined') { - this.setConfig(opt_config); - } + /** + * Configure and start a tween. + * @param {Object=} opt_config See Tweenable.prototype.setConfig() + * @return {Tweenable} + */ + Tweenable.prototype.tween = function (opt_config) { + if (this._isTweening) { + return this; } - /** - * Configure and start a tween. - * @param {Object=} opt_config See Tweenable.prototype.setConfig() - * @return {Tweenable} - */ - Tweenable.prototype.tween = function (opt_config) { - if (this._isTweening) { - return this; - } + // Only set default config if no configuration has been set previously and none is provided now. + if (opt_config !== undefined || !this._configured) { + this.setConfig(opt_config); + } - // Only set default config if no configuration has been set previously and none is provided now. - if (opt_config !== undefined || !this._configured) { - this.setConfig(opt_config); - } + this._timestamp = now(); + this._start(this.get(), this._attachment); + return this.resume(); + }; - this._start(this.get()); - return this.resume(); - }; + /** + * Sets the tween configuration. `config` may have the following options: + * + * - __from__ (_Object=_): Starting position. If omitted, the current state is used. + * - __to__ (_Object=_): Ending position. + * - __duration__ (_number=_): How many milliseconds to animate for. + * - __start__ (_Function(Object)_): Function to execute when the tween begins. Receives the state of the tween as the first parameter. Attachment is the second parameter. + * - __step__ (_Function(Object, *, number)_): Function to execute on every tick. Receives the state of the tween as the first parameter. Attachment is the second parameter, and the time elapsed since the start of the tween is the third parameter. This function is not called on the final step of the animation, but `finish` is. + * - __finish__ (_Function(Object, *)_): Function to execute upon tween completion. Receives the state of the tween as the first parameter. Attachment is the second parameter. + * - __easing__ (_Object|string=_): Easing curve name(s) to use for the tween. + * - __attachment__ (_Object|string|any=_): Value that is attached to this instance and passed on to the step/start/finish methods. + * @param {Object} config + * @return {Tweenable} + */ + Tweenable.prototype.setConfig = function (config) { + config = config || {}; + this._configured = true; - /** - * Sets the tween configuration. `config` may have the following options: - * - * - __from__ (_Object=_): Starting position. If omitted, the current state is used. - * - __to__ (_Object=_): Ending position. - * - __duration__ (_number=_): How many milliseconds to animate for. - * - __start__ (_Function(Object)=_): Function to execute when the tween begins. Receives the state of the tween as the only parameter. - * - __step__ (_Function(Object)=_): Function to execute on every tick. Receives the state of the tween as the only parameter. This function is not called on the final step of the animation, but `finish` is. - * - __finish__ (_Function(Object)=_): Function to execute upon tween completion. Receives the state of the tween as the only parameter. - * - __easing__ (_Object|string=_): Easing curve name(s) to use for the tween. - * @param {Object} config - * @return {Tweenable} - */ - Tweenable.prototype.setConfig = function (config) { - config = config || {}; - this._configured = true; - - // Init the internal state - this._pausedAtTime = null; - this._start = config.start || noop; - this._step = config.step || noop; - this._finish = config.finish || noop; - this._duration = config.duration || DEFAULT_DURATION; - this._currentState = config.from || this.get(); - this._originalState = this.get(); - this._targetState = config.to || this.get(); - this._timestamp = now(); - - // Aliases used below - var currentState = this._currentState; - var targetState = this._targetState; - - // Ensure that there is always something to tween to. - defaults(targetState, currentState); - - this._easing = composeEasingObject( - currentState, config.easing || DEFAULT_EASING); - - this._filterArgs = - [currentState, this._originalState, targetState, this._easing]; - - applyFilter(this, 'tweenCreated'); - return this; - }; + // Attach something to this Tweenable instance (e.g.: a DOM element, an object, a string, etc.); + this._attachment = config.attachment; - /** - * Gets the current state. - * @return {Object} - */ - Tweenable.prototype.get = function () { - return shallowCopy({}, this._currentState); - }; + // Init the internal state + this._pausedAtTime = null; + this._scheduleId = null; + this._start = config.start || noop; + this._step = config.step || noop; + this._finish = config.finish || noop; + this._duration = config.duration || DEFAULT_DURATION; + this._currentState = config.from || this.get(); + this._originalState = this.get(); + this._targetState = config.to || this.get(); - /** - * Sets the current state. - * @param {Object} state - */ - Tweenable.prototype.set = function (state) { - this._currentState = state; - }; + // Aliases used below + var currentState = this._currentState; + var targetState = this._targetState; - /** - * Pauses a tween. Paused tweens can be resumed from the point at which they were paused. This is different than [`stop()`](#stop), as that method causes a tween to start over when it is resumed. - * @return {Tweenable} - */ - Tweenable.prototype.pause = function () { - this._pausedAtTime = now(); - this._isPaused = true; - return this; - }; + // Ensure that there is always something to tween to. + defaults(targetState, currentState); - /** - * Resumes a paused tween. - * @return {Tweenable} - */ - Tweenable.prototype.resume = function () { - if (this._isPaused) { - this._timestamp += now() - this._pausedAtTime; - } + this._easing = composeEasingObject( + currentState, config.easing || DEFAULT_EASING); - this._isPaused = false; - this._isTweening = true; + this._filterArgs = + [currentState, this._originalState, targetState, this._easing]; - var self = this; - this._timeoutHandler = function () { - timeoutHandler(self, self._timestamp, self._duration, self._currentState, - self._originalState, self._targetState, self._easing, self._step, - self._scheduleFunction); - }; + applyFilter(this, 'tweenCreated'); + return this; + }; - this._timeoutHandler(); + /** + * Gets the current state. + * @return {Object} + */ + Tweenable.prototype.get = function () { + return shallowCopy({}, this._currentState); + }; - return this; - }; + /** + * Sets the current state. + * @param {Object} state + */ + Tweenable.prototype.set = function (state) { + this._currentState = state; + }; - /** - * Stops and cancels a tween. - * @param {boolean=} gotoEnd If false or omitted, the tween just stops at its current state, and the "finish" handler is not invoked. If true, the tweened object's values are instantly set to the target values, and "finish" is invoked. - * @return {Tweenable} - */ - Tweenable.prototype.stop = function (gotoEnd) { - this._isTweening = false; - this._isPaused = false; - this._timeoutHandler = noop; + /** + * Pauses a tween. Paused tweens can be resumed from the point at which they were paused. This is different than [`stop()`](#stop), as that method causes a tween to start over when it is resumed. + * @return {Tweenable} + */ + Tweenable.prototype.pause = function () { + this._pausedAtTime = now(); + this._isPaused = true; + return this; + }; - if (gotoEnd) { - shallowCopy(this._currentState, this._targetState); - applyFilter(this, 'afterTweenEnd'); - this._finish.call(this, this._currentState); - } + /** + * Resumes a paused tween. + * @return {Tweenable} + */ + Tweenable.prototype.resume = function () { + if (this._isPaused) { + this._timestamp += now() - this._pausedAtTime; + } - return this; - }; + this._isPaused = false; + this._isTweening = true; - /** - * Returns whether or not a tween is running. - * @return {boolean} - */ - Tweenable.prototype.isPlaying = function () { - return this._isTweening && !this._isPaused; + var self = this; + this._timeoutHandler = function () { + timeoutHandler(self, self._timestamp, self._duration, self._currentState, + self._originalState, self._targetState, self._easing, self._step, + self._scheduleFunction); }; - /** - * Sets a custom schedule function. - * - * If a custom function is not set the default one is used [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) if available, otherwise [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)). - * - * @param {Function(Function,number)} scheduleFunction The function to be called to schedule the next frame to be rendered - */ - Tweenable.prototype.setScheduleFunction = function (scheduleFunction) { - this._scheduleFunction = scheduleFunction; - }; + this._timeoutHandler(); - /** - * `delete`s all "own" properties. Call this when the `Tweenable` instance is no longer needed to free memory. - */ - Tweenable.prototype.dispose = function () { - var prop; - for (prop in this) { - if (this.hasOwnProperty(prop)) { - delete this[prop]; - } - } - }; + return this; + }; - /*! - * Filters are used for transforming the properties of a tween at various - * points in a Tweenable's life cycle. See the README for more info on this. - */ - Tweenable.prototype.filter = {}; - - /*! - * This object contains all of the tweens available to Shifty. It is extendible - simply attach properties to the Tweenable.prototype.formula Object following the same format at linear. - * - * `pos` should be a normalized `number` (between 0 and 1). - */ - Tweenable.prototype.formula = { - linear: function (pos) { - return pos; - } - }; + /** + * Move the state of the animation to a specific point in the tween's timeline. + * If the animation is not running, this will cause the `step` handlers to be + * called. + * @param {millisecond} millisecond The millisecond of the animation to seek to. + * @return {Tweenable} + */ + Tweenable.prototype.seek = function (millisecond) { + this._timestamp = now() - millisecond; - formula = Tweenable.prototype.formula; - - shallowCopy(Tweenable, { - 'now': now - ,'each': each - ,'tweenProps': tweenProps - ,'tweenProp': tweenProp - ,'applyFilter': applyFilter - ,'shallowCopy': shallowCopy - ,'defaults': defaults - ,'composeEasingObject': composeEasingObject - }); + if (!this.isPlaying()) { + this._isTweening = true; + this._isPaused = false; - // `root` is provided in the intro/outro files. + // If the animation is not running, call timeoutHandler to make sure that + // any step handlers are run. + timeoutHandler(this, this._timestamp, this._duration, this._currentState, + this._originalState, this._targetState, this._easing, this._step, + this._scheduleFunction); - // A hook used for unit testing. - if (typeof SHIFTY_DEBUG_NOW === 'function') { - root.timeoutHandler = timeoutHandler; + this._timeoutHandler(); + this.pause(); } - // Bootstrap Tweenable appropriately for the environment. - if (typeof exports === 'object') { - // CommonJS - module.exports = Tweenable; - } else if (typeof define === 'function' && define.amd) { - // AMD - define(function () {return Tweenable;}); - } else if (typeof root.Tweenable === 'undefined') { - // Browser: Make `Tweenable` globally accessible. - root.Tweenable = Tweenable; + return this; + }; + + /** + * Stops and cancels a tween. + * @param {boolean=} gotoEnd If false or omitted, the tween just stops at its current state, and the "finish" handler is not invoked. If true, the tweened object's values are instantly set to the target values, and "finish" is invoked. + * @return {Tweenable} + */ + Tweenable.prototype.stop = function (gotoEnd) { + this._isTweening = false; + this._isPaused = false; + this._timeoutHandler = noop; + + (root.cancelAnimationFrame || + root.webkitCancelAnimationFrame || + root.oCancelAnimationFrame || + root.msCancelAnimationFrame || + root.mozCancelRequestAnimationFrame || + root.clearTimeout)(this._scheduleId); + + if (gotoEnd) { + shallowCopy(this._currentState, this._targetState); + applyFilter(this, 'afterTweenEnd'); + this._finish.call(this, this._currentState, this._attachment); } - return Tweenable; + return this; + }; - } ()); - - window.Tweenable = Tweenable; - /*! - * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). + /** + * Returns whether or not a tween is running. + * @return {boolean} + */ + Tweenable.prototype.isPlaying = function () { + return this._isTweening && !this._isPaused; + }; + + /** + * Sets a custom schedule function. * - * Based on Easing Equations (c) 2003 [Robert Penner](http://www.robertpenner.com/), all rights reserved. This work is [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html). + * If a custom function is not set the default one is used [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) if available, otherwise [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)). + * + * @param {Function(Function,number)} scheduleFunction The function to be called to schedule the next frame to be rendered + */ + Tweenable.prototype.setScheduleFunction = function (scheduleFunction) { + this._scheduleFunction = scheduleFunction; + }; + + /** + * `delete`s all "own" properties. Call this when the `Tweenable` instance is no longer needed to free memory. */ + Tweenable.prototype.dispose = function () { + var prop; + for (prop in this) { + if (this.hasOwnProperty(prop)) { + delete this[prop]; + } + } + }; /*! - * TERMS OF USE - EASING EQUATIONS - * Open source under the BSD License. - * Easing Equations (c) 2003 Robert Penner, all rights reserved. + * Filters are used for transforming the properties of a tween at various + * points in a Tweenable's life cycle. See the README for more info on this. */ + Tweenable.prototype.filter = {}; - ;(function () { - - Tweenable.shallowCopy(Tweenable.prototype.formula, { - easeInQuad: function (pos) { - return Math.pow(pos, 2); - }, - - easeOutQuad: function (pos) { - return -(Math.pow((pos - 1), 2) - 1); - }, - - easeInOutQuad: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,2);} - return -0.5 * ((pos -= 2) * pos - 2); - }, - - easeInCubic: function (pos) { - return Math.pow(pos, 3); - }, - - easeOutCubic: function (pos) { - return (Math.pow((pos - 1), 3) + 1); - }, - - easeInOutCubic: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,3);} - return 0.5 * (Math.pow((pos - 2),3) + 2); - }, - - easeInQuart: function (pos) { - return Math.pow(pos, 4); - }, - - easeOutQuart: function (pos) { - return -(Math.pow((pos - 1), 4) - 1); - }, - - easeInOutQuart: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} - return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); - }, - - easeInQuint: function (pos) { - return Math.pow(pos, 5); - }, - - easeOutQuint: function (pos) { - return (Math.pow((pos - 1), 5) + 1); - }, - - easeInOutQuint: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,5);} - return 0.5 * (Math.pow((pos - 2),5) + 2); - }, - - easeInSine: function (pos) { - return -Math.cos(pos * (Math.PI / 2)) + 1; - }, - - easeOutSine: function (pos) { - return Math.sin(pos * (Math.PI / 2)); - }, - - easeInOutSine: function (pos) { - return (-0.5 * (Math.cos(Math.PI * pos) - 1)); - }, - - easeInExpo: function (pos) { - return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1)); - }, - - easeOutExpo: function (pos) { - return (pos === 1) ? 1 : -Math.pow(2, -10 * pos) + 1; - }, - - easeInOutExpo: function (pos) { - if (pos === 0) {return 0;} - if (pos === 1) {return 1;} - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(2,10 * (pos - 1));} - return 0.5 * (-Math.pow(2, -10 * --pos) + 2); - }, - - easeInCirc: function (pos) { - return -(Math.sqrt(1 - (pos * pos)) - 1); - }, - - easeOutCirc: function (pos) { - return Math.sqrt(1 - Math.pow((pos - 1), 2)); - }, - - easeInOutCirc: function (pos) { - if ((pos /= 0.5) < 1) {return -0.5 * (Math.sqrt(1 - pos * pos) - 1);} - return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1); - }, - - easeOutBounce: function (pos) { - if ((pos) < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, - - easeInBack: function (pos) { - var s = 1.70158; - return (pos) * pos * ((s + 1) * pos - s); - }, - - easeOutBack: function (pos) { - var s = 1.70158; - return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1; - }, - - easeInOutBack: function (pos) { - var s = 1.70158; - if ((pos /= 0.5) < 1) {return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));} - return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); - }, - - elastic: function (pos) { - return -1 * Math.pow(4,-8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1; - }, - - swingFromTo: function (pos) { - var s = 1.70158; - return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) : - 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); - }, - - swingFrom: function (pos) { - var s = 1.70158; - return pos * pos * ((s + 1) * pos - s); - }, - - swingTo: function (pos) { - var s = 1.70158; - return (pos -= 1) * pos * ((s + 1) * pos + s) + 1; - }, - - bounce: function (pos) { - if (pos < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, - - bouncePast: function (pos) { - if (pos < (1 / 2.75)) { - return (7.5625 * pos * pos); - } else if (pos < (2 / 2.75)) { - return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); - } else if (pos < (2.5 / 2.75)) { - return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); - } else { - return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); - } - }, + /*! + * This object contains all of the tweens available to Shifty. It is extendible - simply attach properties to the Tweenable.prototype.formula Object following the same format at linear. + * + * `pos` should be a normalized `number` (between 0 and 1). + */ + Tweenable.prototype.formula = { + linear: function (pos) { + return pos; + } + }; + + formula = Tweenable.prototype.formula; + + shallowCopy(Tweenable, { + 'now': now + ,'each': each + ,'tweenProps': tweenProps + ,'tweenProp': tweenProp + ,'applyFilter': applyFilter + ,'shallowCopy': shallowCopy + ,'defaults': defaults + ,'composeEasingObject': composeEasingObject + }); + + // `root` is provided in the intro/outro files. + + // A hook used for unit testing. + if (typeof SHIFTY_DEBUG_NOW === 'function') { + root.timeoutHandler = timeoutHandler; + } - easeFromTo: function (pos) { - if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} - return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); - }, + // Bootstrap Tweenable appropriately for the environment. + if (typeof exports === 'object') { + // CommonJS + module.exports = Tweenable; + } else if (typeof define === 'function' && define.amd) { + // AMD + define(function () {return Tweenable;}); + } else if (typeof root.Tweenable === 'undefined') { + // Browser: Make `Tweenable` globally accessible. + root.Tweenable = Tweenable; + } - easeFrom: function (pos) { - return Math.pow(pos,4); - }, + return Tweenable; - easeTo: function (pos) { - return Math.pow(pos,0.25); + } ()); + + /*! + * All equations are adapted from Thomas Fuchs' [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js). + * + * Based on Easing Equations (c) 2003 [Robert Penner](http://www.robertpenner.com/), all rights reserved. This work is [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html). + */ + + /*! + * TERMS OF USE - EASING EQUATIONS + * Open source under the BSD License. + * Easing Equations (c) 2003 Robert Penner, all rights reserved. + */ + + ;(function () { + + Tweenable.shallowCopy(Tweenable.prototype.formula, { + easeInQuad: function (pos) { + return Math.pow(pos, 2); + }, + + easeOutQuad: function (pos) { + return -(Math.pow((pos - 1), 2) - 1); + }, + + easeInOutQuad: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,2);} + return -0.5 * ((pos -= 2) * pos - 2); + }, + + easeInCubic: function (pos) { + return Math.pow(pos, 3); + }, + + easeOutCubic: function (pos) { + return (Math.pow((pos - 1), 3) + 1); + }, + + easeInOutCubic: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,3);} + return 0.5 * (Math.pow((pos - 2),3) + 2); + }, + + easeInQuart: function (pos) { + return Math.pow(pos, 4); + }, + + easeOutQuart: function (pos) { + return -(Math.pow((pos - 1), 4) - 1); + }, + + easeInOutQuart: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} + return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); + }, + + easeInQuint: function (pos) { + return Math.pow(pos, 5); + }, + + easeOutQuint: function (pos) { + return (Math.pow((pos - 1), 5) + 1); + }, + + easeInOutQuint: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,5);} + return 0.5 * (Math.pow((pos - 2),5) + 2); + }, + + easeInSine: function (pos) { + return -Math.cos(pos * (Math.PI / 2)) + 1; + }, + + easeOutSine: function (pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + + easeInOutSine: function (pos) { + return (-0.5 * (Math.cos(Math.PI * pos) - 1)); + }, + + easeInExpo: function (pos) { + return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1)); + }, + + easeOutExpo: function (pos) { + return (pos === 1) ? 1 : -Math.pow(2, -10 * pos) + 1; + }, + + easeInOutExpo: function (pos) { + if (pos === 0) {return 0;} + if (pos === 1) {return 1;} + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(2,10 * (pos - 1));} + return 0.5 * (-Math.pow(2, -10 * --pos) + 2); + }, + + easeInCirc: function (pos) { + return -(Math.sqrt(1 - (pos * pos)) - 1); + }, + + easeOutCirc: function (pos) { + return Math.sqrt(1 - Math.pow((pos - 1), 2)); + }, + + easeInOutCirc: function (pos) { + if ((pos /= 0.5) < 1) {return -0.5 * (Math.sqrt(1 - pos * pos) - 1);} + return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1); + }, + + easeOutBounce: function (pos) { + if ((pos) < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); } - }); + }, + + easeInBack: function (pos) { + var s = 1.70158; + return (pos) * pos * ((s + 1) * pos - s); + }, + + easeOutBack: function (pos) { + var s = 1.70158; + return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1; + }, + + easeInOutBack: function (pos) { + var s = 1.70158; + if ((pos /= 0.5) < 1) {return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));} + return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); + }, + + elastic: function (pos) { + return -1 * Math.pow(4,-8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1; + }, + + swingFromTo: function (pos) { + var s = 1.70158; + return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) : + 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2); + }, + + swingFrom: function (pos) { + var s = 1.70158; + return pos * pos * ((s + 1) * pos - s); + }, + + swingTo: function (pos) { + var s = 1.70158; + return (pos -= 1) * pos * ((s + 1) * pos + s) + 1; + }, + + bounce: function (pos) { + if (pos < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); + } + }, + + bouncePast: function (pos) { + if (pos < (1 / 2.75)) { + return (7.5625 * pos * pos); + } else if (pos < (2 / 2.75)) { + return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75); + } else if (pos < (2.5 / 2.75)) { + return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375); + } else { + return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375); + } + }, - }()); + easeFromTo: function (pos) { + if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);} + return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2); + }, - /*! - * The Bezier magic in this file is adapted/copied almost wholesale from - * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js), - * which was adapted from Apple code (which probably came from - * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)). - * Special thanks to Apple and Thomas Fuchs for much of this code. - */ + easeFrom: function (pos) { + return Math.pow(pos,4); + }, + easeTo: function (pos) { + return Math.pow(pos,0.25); + } + }); + + }()); + + /*! + * The Bezier magic in this file is adapted/copied almost wholesale from + * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js), + * which was adapted from Apple code (which probably came from + * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)). + * Special thanks to Apple and Thomas Fuchs for much of this code. + */ + + /*! + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder(s) nor the names of any + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + ;(function () { + // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/ + function cubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration) { + var ax = 0,bx = 0,cx = 0,ay = 0,by = 0,cy = 0; + function sampleCurveX(t) {return ((ax * t + bx) * t + cx) * t;} + function sampleCurveY(t) {return ((ay * t + by) * t + cy) * t;} + function sampleCurveDerivativeX(t) {return (3.0 * ax * t + 2.0 * bx) * t + cx;} + function solveEpsilon(duration) {return 1.0 / (200.0 * duration);} + function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));} + function fabs(n) {if (n >= 0) {return n;}else {return 0 - n;}} + function solveCurveX(x,epsilon) { + var t0,t1,t2,x2,d2,i; + for (t2 = x, i = 0; i < 8; i++) {x2 = sampleCurveX(t2) - x; if (fabs(x2) < epsilon) {return t2;} d2 = sampleCurveDerivativeX(t2); if (fabs(d2) < 1e-6) {break;} t2 = t2 - x2 / d2;} + t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) {return t0;} if (t2 > t1) {return t1;} + while (t0 < t1) {x2 = sampleCurveX(t2); if (fabs(x2 - x) < epsilon) {return t2;} if (x > x2) {t0 = t2;}else {t1 = t2;} t2 = (t1 - t0) * 0.5 + t0;} + return t2; // Failure. + } + cx = 3.0 * p1x; bx = 3.0 * (p2x - p1x) - cx; ax = 1.0 - cx - bx; cy = 3.0 * p1y; by = 3.0 * (p2y - p1y) - cy; ay = 1.0 - cy - by; + return solve(t, solveEpsilon(duration)); + } /*! - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * getCubicBezierTransition(x1, y1, x2, y2) -> Function * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * Generates a transition easing function that is compatible + * with WebKit's CSS transitions `-webkit-transition-timing-function` + * CSS property. * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * The W3C has more information about + * + * CSS3 transition timing functions. * - * 3. Neither the name of the copyright holder(s) nor the names of any - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {function} */ - ;(function () { - // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/ - function cubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration) { - var ax = 0,bx = 0,cx = 0,ay = 0,by = 0,cy = 0; - function sampleCurveX(t) {return ((ax * t + bx) * t + cx) * t;} - function sampleCurveY(t) {return ((ay * t + by) * t + cy) * t;} - function sampleCurveDerivativeX(t) {return (3.0 * ax * t + 2.0 * bx) * t + cx;} - function solveEpsilon(duration) {return 1.0 / (200.0 * duration);} - function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));} - function fabs(n) {if (n >= 0) {return n;}else {return 0 - n;}} - function solveCurveX(x,epsilon) { - var t0,t1,t2,x2,d2,i; - for (t2 = x, i = 0; i < 8; i++) {x2 = sampleCurveX(t2) - x; if (fabs(x2) < epsilon) {return t2;} d2 = sampleCurveDerivativeX(t2); if (fabs(d2) < 1e-6) {break;} t2 = t2 - x2 / d2;} - t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) {return t0;} if (t2 > t1) {return t1;} - while (t0 < t1) {x2 = sampleCurveX(t2); if (fabs(x2 - x) < epsilon) {return t2;} if (x > x2) {t0 = t2;}else {t1 = t2;} t2 = (t1 - t0) * 0.5 + t0;} - return t2; // Failure. - } - cx = 3.0 * p1x; bx = 3.0 * (p2x - p1x) - cx; ax = 1.0 - cx - bx; cy = 3.0 * p1y; by = 3.0 * (p2y - p1y) - cy; ay = 1.0 - cy - by; - return solve(t, solveEpsilon(duration)); - } - /*! - * getCubicBezierTransition(x1, y1, x2, y2) -> Function - * - * Generates a transition easing function that is compatible - * with WebKit's CSS transitions `-webkit-transition-timing-function` - * CSS property. - * - * The W3C has more information about - * - * CSS3 transition timing functions. - * - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @return {function} - */ - function getCubicBezierTransition (x1, y1, x2, y2) { - return function (pos) { - return cubicBezierAtTime(pos,x1,y1,x2,y2,1); - }; - } - // End ported code - - /** - * Creates a Bezier easing function and attaches it to `Tweenable.prototype.formula`. This function gives you total control over the easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing the curves you can make with this function. - * - * @param {string} name The name of the easing curve. Overwrites the old easing function on Tweenable.prototype.formula if it exists. - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @return {function} The easing function that was attached to Tweenable.prototype.formula. - */ - Tweenable.setBezierFunction = function (name, x1, y1, x2, y2) { - var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2); - cubicBezierTransition.x1 = x1; - cubicBezierTransition.y1 = y1; - cubicBezierTransition.x2 = x2; - cubicBezierTransition.y2 = y2; - - return Tweenable.prototype.formula[name] = cubicBezierTransition; + function getCubicBezierTransition (x1, y1, x2, y2) { + return function (pos) { + return cubicBezierAtTime(pos,x1,y1,x2,y2,1); }; + } + // End ported code + /** + * Creates a Bezier easing function and attaches it to `Tweenable.prototype.formula`. This function gives you total control over the easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing the curves you can make with this function. + * + * @param {string} name The name of the easing curve. Overwrites the old easing function on Tweenable.prototype.formula if it exists. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {function} The easing function that was attached to Tweenable.prototype.formula. + */ + Tweenable.setBezierFunction = function (name, x1, y1, x2, y2) { + var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2); + cubicBezierTransition.x1 = x1; + cubicBezierTransition.y1 = y1; + cubicBezierTransition.x2 = x2; + cubicBezierTransition.y2 = y2; - /** - * `delete`s an easing function from `Tweenable.prototype.formula`. Be careful with this method, as it `delete`s whatever easing formula matches `name` (which means you can delete default Shifty easing functions). - * - * @param {string} name The name of the easing function to delete. - * @return {function} - */ - Tweenable.unsetBezierFunction = function (name) { - delete Tweenable.prototype.formula[name]; - }; + return Tweenable.prototype.formula[name] = cubicBezierTransition; + }; - })(); - ;(function () { + /** + * `delete`s an easing function from `Tweenable.prototype.formula`. Be careful with this method, as it `delete`s whatever easing formula matches `name` (which means you can delete default Shifty easing functions). + * + * @param {string} name The name of the easing function to delete. + * @return {function} + */ + Tweenable.unsetBezierFunction = function (name) { + delete Tweenable.prototype.formula[name]; + }; - function getInterpolatedValues ( - from, current, targetState, position, easing) { - return Tweenable.tweenProps( - position, current, from, targetState, 1, 0, easing); - } + })(); - // Fake a Tweenable and patch some internals. This approach allows us to - // skip uneccessary processing and object recreation, cutting down on garbage - // collection pauses. - var mockTweenable = new Tweenable(); - mockTweenable._filterArgs = []; - - /** - * Compute the midpoint of two Objects. This method effectively calculates a specific frame of animation that [Tweenable#tween](shifty.core.js.html#tween) does many times over the course of a tween. - * - * Example: - * - * ``` - * var interpolatedValues = Tweenable.interpolate({ - * width: '100px', - * opacity: 0, - * color: '#fff' - * }, { - * width: '200px', - * opacity: 1, - * color: '#000' - * }, 0.5); - * - * console.log(interpolatedValues); - * // {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"} - * ``` - * - * @param {Object} from The starting values to tween from. - * @param {Object} targetState The ending values to tween to. - * @param {number} position The normalized position value (between 0.0 and 1.0) to interpolate the values between `from` and `to` for. `from` represents 0 and `to` represents `1`. - * @param {string|Object} easing The easing curve(s) to calculate the midpoint against. You can reference any easing function attached to `Tweenable.prototype.formula`. If omitted, this defaults to "linear". - * @return {Object} - */ - Tweenable.interpolate = function (from, targetState, position, easing) { - var current = Tweenable.shallowCopy({}, from); - var easingObject = Tweenable.composeEasingObject( - from, easing || 'linear'); - - mockTweenable.set({}); - - // Alias and reuse the _filterArgs array instead of recreating it. - var filterArgs = mockTweenable._filterArgs; - filterArgs.length = 0; - filterArgs[0] = current; - filterArgs[1] = from; - filterArgs[2] = targetState; - filterArgs[3] = easingObject; - - // Any defined value transformation must be applied - Tweenable.applyFilter(mockTweenable, 'tweenCreated'); - Tweenable.applyFilter(mockTweenable, 'beforeTween'); - - var interpolatedValues = getInterpolatedValues( - from, current, targetState, position, easingObject); - - // Transform values back into their original format - Tweenable.applyFilter(mockTweenable, 'afterTween'); - - return interpolatedValues; - }; + ;(function () { + + function getInterpolatedValues ( + from, current, targetState, position, easing) { + return Tweenable.tweenProps( + position, current, from, targetState, 1, 0, easing); + } - }()); + // Fake a Tweenable and patch some internals. This approach allows us to + // skip uneccessary processing and object recreation, cutting down on garbage + // collection pauses. + var mockTweenable = new Tweenable(); + mockTweenable._filterArgs = []; /** - * Adds string interpolation support to Shifty. + * Compute the midpoint of two Objects. This method effectively calculates a specific frame of animation that [Tweenable#tween](shifty.core.js.html#tween) does many times over the course of a tween. * - * The Token extension allows Shifty to tween numbers inside of strings. Among other things, this allows you to animate CSS properties. For example, you can do this: + * Example: * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(45px)'}, - * to: { transform: 'translateX(90xp)'} - * }); - * ``` + * var interpolatedValues = Tweenable.interpolate({ + * width: '100px', + * opacity: 0, + * color: '#fff' + * }, { + * width: '200px', + * opacity: 1, + * color: '#000' + * }, 0.5); * - * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate: + * console.log(interpolatedValues); + * // {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"} * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(45px)'}, - * to: { transform: 'translateX(90px)'}, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` - * - * The above snippet will log something like this in the console: - * - * ``` - * translateX(60.3px) - * ... - * translateX(76.05px) - * ... - * translateX(90px) - * ``` - * - * Another use for this is animating colors: - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { color: 'rgb(0,255,0)'}, - * to: { color: 'rgb(255,0,255)'}, - * step: function (state) { - * console.log(state.color); - * } - * }); - * ``` - * - * The above snippet will log something like this: - * - * ``` - * rgb(84,170,84) - * ... - * rgb(170,84,170) - * ... - * rgb(255,0,255) - * ``` - * - * This extension also supports hexadecimal colors, in both long (`#ff00ff`) and short (`#f0f`) forms. Be aware that hexadecimal input values will be converted into the equivalent RGB output values. This is done to optimize for performance. - * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { color: '#0f0'}, - * to: { color: '#f0f'}, - * step: function (state) { - * console.log(state.color); - * } - * }); - * ``` - * - * This snippet will generate the same output as the one before it because equivalent values were supplied (just in hexadecimal form rather than RGB): + * @param {Object} from The starting values to tween from. + * @param {Object} targetState The ending values to tween to. + * @param {number} position The normalized position value (between 0.0 and 1.0) to interpolate the values between `from` and `to` for. `from` represents 0 and `to` represents `1`. + * @param {string|Object} easing The easing curve(s) to calculate the midpoint against. You can reference any easing function attached to `Tweenable.prototype.formula`. If omitted, this defaults to "linear". + * @return {Object} + */ + Tweenable.interpolate = function (from, targetState, position, easing) { + var current = Tweenable.shallowCopy({}, from); + var easingObject = Tweenable.composeEasingObject( + from, easing || 'linear'); + + mockTweenable.set({}); + + // Alias and reuse the _filterArgs array instead of recreating it. + var filterArgs = mockTweenable._filterArgs; + filterArgs.length = 0; + filterArgs[0] = current; + filterArgs[1] = from; + filterArgs[2] = targetState; + filterArgs[3] = easingObject; + + // Any defined value transformation must be applied + Tweenable.applyFilter(mockTweenable, 'tweenCreated'); + Tweenable.applyFilter(mockTweenable, 'beforeTween'); + + var interpolatedValues = getInterpolatedValues( + from, current, targetState, position, easingObject); + + // Transform values back into their original format + Tweenable.applyFilter(mockTweenable, 'afterTween'); + + return interpolatedValues; + }; + + }()); + + /** + * Adds string interpolation support to Shifty. + * + * The Token extension allows Shifty to tween numbers inside of strings. Among + * other things, this allows you to animate CSS properties. For example, you + * can do this: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(45px)'}, + * to: { transform: 'translateX(90xp)'} + * }); + * + * ` ` + * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(45px)'}, + * to: { transform: 'translateX(90px)'}, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet will log something like this in the console: + * + * translateX(60.3px) + * ... + * translateX(76.05px) + * ... + * translateX(90px) + * + * ` ` + * Another use for this is animating colors: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { color: 'rgb(0,255,0)'}, + * to: { color: 'rgb(255,0,255)'}, + * step: function (state) { + * console.log(state.color); + * } + * }); + * + * ` ` + * The above snippet will log something like this: + * + * rgb(84,170,84) + * ... + * rgb(170,84,170) + * ... + * rgb(255,0,255) + * + * ` ` + * This extension also supports hexadecimal colors, in both long (`#ff00ff`) + * and short (`#f0f`) forms. Be aware that hexadecimal input values will be + * converted into the equivalent RGB output values. This is done to optimize + * for performance. + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { color: '#0f0'}, + * to: { color: '#f0f'}, + * step: function (state) { + * console.log(state.color); + * } + * }); + * + * ` ` + * This snippet will generate the same output as the one before it because + * equivalent values were supplied (just in hexadecimal form rather than RGB): + * + * rgb(84,170,84) + * ... + * rgb(170,84,170) + * ... + * rgb(255,0,255) + * + * ` ` + * ` ` + * ## Easing support + * + * Easing works somewhat differently in the Token extension. This is because + * some CSS properties have multiple values in them, and you might need to + * tween each value along its own easing curve. A basic example: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(0px) translateY(0px)'}, + * to: { transform: 'translateX(100px) translateY(100px)'}, + * easing: { transform: 'easeInQuad' }, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet create values like this: + * + * translateX(11.560000000000002px) translateY(11.560000000000002px) + * ... + * translateX(46.24000000000001px) translateY(46.24000000000001px) + * ... + * translateX(100px) translateY(100px) + * + * ` ` + * In this case, the values for `translateX` and `translateY` are always the + * same for each step of the tween, because they have the same start and end + * points and both use the same easing curve. We can also tween `translateX` + * and `translateY` along independent curves: + * + * var tweenable = new Tweenable(); + * tweenable.tween({ + * from: { transform: 'translateX(0px) translateY(0px)'}, + * to: { transform: 'translateX(100px) translateY(100px)'}, + * easing: { transform: 'easeInQuad bounce' }, + * step: function (state) { + * console.log(state.transform); + * } + * }); + * + * ` ` + * The above snippet create values like this: + * + * translateX(10.89px) translateY(82.355625px) + * ... + * translateX(44.89000000000001px) translateY(86.73062500000002px) + * ... + * translateX(100px) translateY(100px) + * + * ` ` + * `translateX` and `translateY` are not in sync anymore, because `easeInQuad` + * was specified for `translateX` and `bounce` for `translateY`. Mixing and + * matching easing curves can make for some interesting motion in your + * animations. + * + * The order of the space-separated easing curves correspond the token values + * they apply to. If there are more token values than easing curves listed, + * the last easing curve listed is used. + */ + function token () { + // Functionality for this extension runs implicitly if it is loaded. + } /*!*/ + + // token function is defined above only so that dox-foundation sees it as + // documentation and renders it. It is never used, and is optimized away at + // build time. + + ;(function (Tweenable) { + + /*! + * @typedef {{ + * formatString: string + * chunkNames: Array. + * }} + */ + var formatManifest; + + // CONSTANTS + + var R_NUMBER_COMPONENT = /(\d|\-|\.)/; + var R_FORMAT_CHUNKS = /([^\-0-9\.]+)/g; + var R_UNFORMATTED_VALUES = /[0-9.\-]+/g; + var R_RGB = new RegExp( + 'rgb\\(' + R_UNFORMATTED_VALUES.source + + (/,\s*/.source) + R_UNFORMATTED_VALUES.source + + (/,\s*/.source) + R_UNFORMATTED_VALUES.source + '\\)', 'g'); + var R_RGB_PREFIX = /^.*\(/; + var R_HEX = /#([0-9]|[a-f]){3,6}/gi; + var VALUE_PLACEHOLDER = 'VAL'; + + // HELPERS + + var getFormatChunksFrom_accumulator = []; + /*! + * @param {Array.number} rawValues + * @param {string} prefix * - * ``` - * rgb(84,170,84) - * ... - * rgb(170,84,170) - * ... - * rgb(255,0,255) - * ``` + * @return {Array.} + */ + function getFormatChunksFrom (rawValues, prefix) { + getFormatChunksFrom_accumulator.length = 0; + + var rawValuesLength = rawValues.length; + var i; + + for (i = 0; i < rawValuesLength; i++) { + getFormatChunksFrom_accumulator.push('_' + prefix + '_' + i); + } + + return getFormatChunksFrom_accumulator; + } + + /*! + * @param {string} formattedString * - * ## Easing support + * @return {string} + */ + function getFormatStringFrom (formattedString) { + var chunks = formattedString.match(R_FORMAT_CHUNKS); + + if (!chunks) { + // chunks will be null if there were no tokens to parse in + // formattedString (for example, if formattedString is '2'). Coerce + // chunks to be useful here. + chunks = ['', '']; + + // If there is only one chunk, assume that the string is a number + // followed by a token... + // NOTE: This may be an unwise assumption. + } else if (chunks.length === 1 || + // ...or if the string starts with a number component (".", "-", or a + // digit)... + formattedString[0].match(R_NUMBER_COMPONENT)) { + // ...prepend an empty string here to make sure that the formatted number + // is properly replaced by VALUE_PLACEHOLDER + chunks.unshift(''); + } + + return chunks.join(VALUE_PLACEHOLDER); + } + + /*! + * Convert all hex color values within a string to an rgb string. * - * Easing works somewhat differently in the Token extension. This is because some CSS properties have multiple values in them, and you might need to tween each value along its own easing curve. A basic example: + * @param {Object} stateObject * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(0px) translateY(0px)'}, - * to: { transform: 'translateX(100px) translateY(100px)'}, - * easing: { transform: 'easeInQuad' }, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` + * @return {Object} The modified obj + */ + function sanitizeObjectForHexProps (stateObject) { + Tweenable.each(stateObject, function (prop) { + var currentProp = stateObject[prop]; + + if (typeof currentProp === 'string' && currentProp.match(R_HEX)) { + stateObject[prop] = sanitizeHexChunksToRGB(currentProp); + } + }); + } + + /*! + * @param {string} str * - * The above snippet create values like this: + * @return {string} + */ + function sanitizeHexChunksToRGB (str) { + return filterStringChunks(R_HEX, str, convertHexToRGB); + } + + /*! + * @param {string} hexString * - * ``` - * translateX(11.560000000000002px) translateY(11.560000000000002px) - * ... - * translateX(46.24000000000001px) translateY(46.24000000000001px) - * ... - * translateX(100px) translateY(100px) - * ``` + * @return {string} + */ + function convertHexToRGB (hexString) { + var rgbArr = hexToRGBArray(hexString); + return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')'; + } + + var hexToRGBArray_returnArray = []; + /*! + * Convert a hexadecimal string to an array with three items, one each for + * the red, blue, and green decimal values. * - * In this case, the values for `translateX` and `translateY` are always the same for each step of the tween, because they have the same start and end points and both use the same easing curve. We can also tween `translateX` and `translateY` along independent curves: + * @param {string} hex A hexadecimal string. * - * ``` - * var tweenable = new Tweenable(); - * tweenable.tween({ - * from: { transform: 'translateX(0px) translateY(0px)'}, - * to: { transform: 'translateX(100px) translateY(100px)'}, - * easing: { transform: 'easeInQuad bounce' }, - * step: function (state) { - * console.log(state.transform); - * } - * }); - * ``` + * @returns {Array.} The converted Array of RGB values if `hex` is a + * valid string, or an Array of three 0's. + */ + function hexToRGBArray (hex) { + + hex = hex.replace(/#/, ''); + + // If the string is a shorthand three digit hex notation, normalize it to + // the standard six digit notation + if (hex.length === 3) { + hex = hex.split(''); + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2)); + hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2)); + hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2)); + + return hexToRGBArray_returnArray; + } + + /*! + * Convert a base-16 number to base-10. * - * The above snippet create values like this: + * @param {Number|String} hex The value to convert * - * ``` - * translateX(10.89px) translateY(82.355625px) - * ... - * translateX(44.89000000000001px) translateY(86.73062500000002px) - * ... - * translateX(100px) translateY(100px) - * ``` + * @returns {Number} The base-10 equivalent of `hex`. + */ + function hexToDec (hex) { + return parseInt(hex, 16); + } + + /*! + * Runs a filter operation on all chunks of a string that match a RegExp * - * `translateX` and `translateY` are not in sync anymore, because `easeInQuad` was specified for `translateX` and `bounce` for `translateY`. Mixing and matching easing curves can make for some interesting motion in your animations. + * @param {RegExp} pattern + * @param {string} unfilteredString + * @param {function(string)} filter * - * The order of the space-separated easing curves correspond the token values they apply to. If there are more token values than easing curves listed, the last easing curve listed is used. + * @return {string} */ - function token () { - // Functionality for this extension runs implicitly if it is loaded. - } /*!*/ - - // token function is defined above only so that dox-foundation sees it as - // documentation and renders it. It is never used, and is optimized away at - // build time. - - ;(function (Tweenable) { - - /*! - * @typedef {{ - * formatString: string - * chunkNames: Array. - * }} - */ - var formatManifest; - - // CONSTANTS - - var R_NUMBER_COMPONENT = /(\d|\-|\.)/; - var R_FORMAT_CHUNKS = /([^\-0-9\.]+)/g; - var R_UNFORMATTED_VALUES = /[0-9.\-]+/g; - var R_RGB = new RegExp( - 'rgb\\(' + R_UNFORMATTED_VALUES.source + - (/,\s*/.source) + R_UNFORMATTED_VALUES.source + - (/,\s*/.source) + R_UNFORMATTED_VALUES.source + '\\)', 'g'); - var R_RGB_PREFIX = /^.*\(/; - var R_HEX = /#([0-9]|[a-f]){3,6}/gi; - var VALUE_PLACEHOLDER = 'VAL'; - - // HELPERS - - var getFormatChunksFrom_accumulator = []; - /*! - * @param {Array.number} rawValues - * @param {string} prefix - * - * @return {Array.} - */ - function getFormatChunksFrom (rawValues, prefix) { - getFormatChunksFrom_accumulator.length = 0; - - var rawValuesLength = rawValues.length; - var i; - - for (i = 0; i < rawValuesLength; i++) { - getFormatChunksFrom_accumulator.push('_' + prefix + '_' + i); + function filterStringChunks (pattern, unfilteredString, filter) { + var pattenMatches = unfilteredString.match(pattern); + var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER); + + if (pattenMatches) { + var pattenMatchesLength = pattenMatches.length; + var currentChunk; + + for (var i = 0; i < pattenMatchesLength; i++) { + currentChunk = pattenMatches.shift(); + filteredString = filteredString.replace( + VALUE_PLACEHOLDER, filter(currentChunk)); } - - return getFormatChunksFrom_accumulator; } - /*! - * @param {string} formattedString - * - * @return {string} - */ - function getFormatStringFrom (formattedString) { - var chunks = formattedString.match(R_FORMAT_CHUNKS); - - if (!chunks) { - // chunks will be null if there were no tokens to parse in - // formattedString (for example, if formattedString is '2'). Coerce - // chunks to be useful here. - chunks = ['', '']; - - // If there is only one chunk, assume that the string is a number - // followed by a token... - // NOTE: This may be an unwise assumption. - } else if (chunks.length === 1 || - // ...or if the string starts with a number component (".", "-", or a - // digit)... - formattedString[0].match(R_NUMBER_COMPONENT)) { - // ...prepend an empty string here to make sure that the formatted number - // is properly replaced by VALUE_PLACEHOLDER - chunks.unshift(''); - } + return filteredString; + } - return chunks.join(VALUE_PLACEHOLDER); - } + /*! + * Check for floating point values within rgb strings and rounds them. + * + * @param {string} formattedString + * + * @return {string} + */ + function sanitizeRGBChunks (formattedString) { + return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk); + } - /*! - * Convert all hex color values within a string to an rgb string. - * - * @param {Object} stateObject - * - * @return {Object} The modified obj - */ - function sanitizeObjectForHexProps (stateObject) { - Tweenable.each(stateObject, function (prop) { - var currentProp = stateObject[prop]; - - if (typeof currentProp === 'string' && currentProp.match(R_HEX)) { - stateObject[prop] = sanitizeHexChunksToRGB(currentProp); - } - }); - } + /*! + * @param {string} rgbChunk + * + * @return {string} + */ + function sanitizeRGBChunk (rgbChunk) { + var numbers = rgbChunk.match(R_UNFORMATTED_VALUES); + var numbersLength = numbers.length; + var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0]; - /*! - * @param {string} str - * - * @return {string} - */ - function sanitizeHexChunksToRGB (str) { - return filterStringChunks(R_HEX, str, convertHexToRGB); + for (var i = 0; i < numbersLength; i++) { + sanitizedString += parseInt(numbers[i], 10) + ','; } - /*! - * @param {string} hexString - * - * @return {string} - */ - function convertHexToRGB (hexString) { - var rgbArr = hexToRGBArray(hexString); - return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')'; - } + sanitizedString = sanitizedString.slice(0, -1) + ')'; - var hexToRGBArray_returnArray = []; - /*! - * Convert a hexadecimal string to an array with three items, one each for - * the red, blue, and green decimal values. - * - * @param {string} hex A hexadecimal string. - * - * @returns {Array.} The converted Array of RGB values if `hex` is a - * valid string, or an Array of three 0's. - */ - function hexToRGBArray (hex) { - - hex = hex.replace(/#/, ''); - - // If the string is a shorthand three digit hex notation, normalize it to - // the standard six digit notation - if (hex.length === 3) { - hex = hex.split(''); - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; - } + return sanitizedString; + } - hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2)); - hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2)); - hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2)); + /*! + * @param {Object} stateObject + * + * @return {Object} An Object of formatManifests that correspond to + * the string properties of stateObject + */ + function getFormatManifests (stateObject) { + var manifestAccumulator = {}; - return hexToRGBArray_returnArray; - } + Tweenable.each(stateObject, function (prop) { + var currentProp = stateObject[prop]; - /*! - * Convert a base-16 number to base-10. - * - * @param {Number|String} hex The value to convert - * - * @returns {Number} The base-10 equivalent of `hex`. - */ - function hexToDec (hex) { - return parseInt(hex, 16); - } + if (typeof currentProp === 'string') { + var rawValues = getValuesFrom(currentProp); - /*! - * Runs a filter operation on all chunks of a string that match a RegExp - * - * @param {RegExp} pattern - * @param {string} unfilteredString - * @param {function(string)} filter - * - * @return {string} - */ - function filterStringChunks (pattern, unfilteredString, filter) { - var pattenMatches = unfilteredString.match(pattern); - var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER); - - if (pattenMatches) { - var pattenMatchesLength = pattenMatches.length; - var currentChunk; - - for (var i = 0; i < pattenMatchesLength; i++) { - currentChunk = pattenMatches.shift(); - filteredString = filteredString.replace( - VALUE_PLACEHOLDER, filter(currentChunk)); - } + manifestAccumulator[prop] = { + 'formatString': getFormatStringFrom(currentProp) + ,'chunkNames': getFormatChunksFrom(rawValues, prop) + }; } + }); - return filteredString; - } + return manifestAccumulator; + } - /*! - * Check for floating point values within rgb strings and rounds them. - * - * @param {string} formattedString - * - * @return {string} - */ - function sanitizeRGBChunks (formattedString) { - return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk); - } + /*! + * @param {Object} stateObject + * @param {Object} formatManifests + */ + function expandFormattedProperties (stateObject, formatManifests) { + Tweenable.each(formatManifests, function (prop) { + var currentProp = stateObject[prop]; + var rawValues = getValuesFrom(currentProp); + var rawValuesLength = rawValues.length; - /*! - * @param {string} rgbChunk - * - * @return {string} - */ - function sanitizeRGBChunk (rgbChunk) { - var numbers = rgbChunk.match(R_UNFORMATTED_VALUES); - var numbersLength = numbers.length; - var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0]; - - for (var i = 0; i < numbersLength; i++) { - sanitizedString += parseInt(numbers[i], 10) + ','; + for (var i = 0; i < rawValuesLength; i++) { + stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i]; } - sanitizedString = sanitizedString.slice(0, -1) + ')'; - - return sanitizedString; - } + delete stateObject[prop]; + }); + } - /*! - * @param {Object} stateObject - * - * @return {Object} An Object of formatManifests that correspond to - * the string properties of stateObject - */ - function getFormatManifests (stateObject) { - var manifestAccumulator = {}; - - Tweenable.each(stateObject, function (prop) { - var currentProp = stateObject[prop]; - - if (typeof currentProp === 'string') { - var rawValues = getValuesFrom(currentProp); - - manifestAccumulator[prop] = { - 'formatString': getFormatStringFrom(currentProp) - ,'chunkNames': getFormatChunksFrom(rawValues, prop) - }; - } - }); + /*! + * @param {Object} stateObject + * @param {Object} formatManifests + */ + function collapseFormattedProperties (stateObject, formatManifests) { + Tweenable.each(formatManifests, function (prop) { + var currentProp = stateObject[prop]; + var formatChunks = extractPropertyChunks( + stateObject, formatManifests[prop].chunkNames); + var valuesList = getValuesList( + formatChunks, formatManifests[prop].chunkNames); + currentProp = getFormattedValues( + formatManifests[prop].formatString, valuesList); + stateObject[prop] = sanitizeRGBChunks(currentProp); + }); + } - return manifestAccumulator; + /*! + * @param {Object} stateObject + * @param {Array.} chunkNames + * + * @return {Object} The extracted value chunks. + */ + function extractPropertyChunks (stateObject, chunkNames) { + var extractedValues = {}; + var currentChunkName, chunkNamesLength = chunkNames.length; + + for (var i = 0; i < chunkNamesLength; i++) { + currentChunkName = chunkNames[i]; + extractedValues[currentChunkName] = stateObject[currentChunkName]; + delete stateObject[currentChunkName]; } - /*! - * @param {Object} stateObject - * @param {Object} formatManifests - */ - function expandFormattedProperties (stateObject, formatManifests) { - Tweenable.each(formatManifests, function (prop) { - var currentProp = stateObject[prop]; - var rawValues = getValuesFrom(currentProp); - var rawValuesLength = rawValues.length; + return extractedValues; + } - for (var i = 0; i < rawValuesLength; i++) { - stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i]; - } + var getValuesList_accumulator = []; + /*! + * @param {Object} stateObject + * @param {Array.} chunkNames + * + * @return {Array.} + */ + function getValuesList (stateObject, chunkNames) { + getValuesList_accumulator.length = 0; + var chunkNamesLength = chunkNames.length; - delete stateObject[prop]; - }); + for (var i = 0; i < chunkNamesLength; i++) { + getValuesList_accumulator.push(stateObject[chunkNames[i]]); } - /*! - * @param {Object} stateObject - * @param {Object} formatManifests - */ - function collapseFormattedProperties (stateObject, formatManifests) { - Tweenable.each(formatManifests, function (prop) { - var currentProp = stateObject[prop]; - var formatChunks = extractPropertyChunks( - stateObject, formatManifests[prop].chunkNames); - var valuesList = getValuesList( - formatChunks, formatManifests[prop].chunkNames); - currentProp = getFormattedValues( - formatManifests[prop].formatString, valuesList); - stateObject[prop] = sanitizeRGBChunks(currentProp); - }); - } + return getValuesList_accumulator; + } - /*! - * @param {Object} stateObject - * @param {Array.} chunkNames - * - * @return {Object} The extracted value chunks. - */ - function extractPropertyChunks (stateObject, chunkNames) { - var extractedValues = {}; - var currentChunkName, chunkNamesLength = chunkNames.length; - - for (var i = 0; i < chunkNamesLength; i++) { - currentChunkName = chunkNames[i]; - extractedValues[currentChunkName] = stateObject[currentChunkName]; - delete stateObject[currentChunkName]; - } + /*! + * @param {string} formatString + * @param {Array.} rawValues + * + * @return {string} + */ + function getFormattedValues (formatString, rawValues) { + var formattedValueString = formatString; + var rawValuesLength = rawValues.length; - return extractedValues; + for (var i = 0; i < rawValuesLength; i++) { + formattedValueString = formattedValueString.replace( + VALUE_PLACEHOLDER, +rawValues[i].toFixed(4)); } - var getValuesList_accumulator = []; - /*! - * @param {Object} stateObject - * @param {Array.} chunkNames - * - * @return {Array.} - */ - function getValuesList (stateObject, chunkNames) { - getValuesList_accumulator.length = 0; - var chunkNamesLength = chunkNames.length; - - for (var i = 0; i < chunkNamesLength; i++) { - getValuesList_accumulator.push(stateObject[chunkNames[i]]); - } - - return getValuesList_accumulator; - } + return formattedValueString; + } - /*! - * @param {string} formatString - * @param {Array.} rawValues - * - * @return {string} - */ - function getFormattedValues (formatString, rawValues) { - var formattedValueString = formatString; - var rawValuesLength = rawValues.length; + /*! + * Note: It's the duty of the caller to convert the Array elements of the + * return value into numbers. This is a performance optimization. + * + * @param {string} formattedString + * + * @return {Array.|null} + */ + function getValuesFrom (formattedString) { + return formattedString.match(R_UNFORMATTED_VALUES); + } - for (var i = 0; i < rawValuesLength; i++) { - formattedValueString = formattedValueString.replace( - VALUE_PLACEHOLDER, +rawValues[i].toFixed(4)); + /*! + * @param {Object} easingObject + * @param {Object} tokenData + */ + function expandEasingObject (easingObject, tokenData) { + Tweenable.each(tokenData, function (prop) { + var currentProp = tokenData[prop]; + var chunkNames = currentProp.chunkNames; + var chunkLength = chunkNames.length; + var easingChunks = easingObject[prop].split(' '); + var lastEasingChunk = easingChunks[easingChunks.length - 1]; + + for (var i = 0; i < chunkLength; i++) { + easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk; } - return formattedValueString; - } - - /*! - * Note: It's the duty of the caller to convert the Array elements of the - * return value into numbers. This is a performance optimization. - * - * @param {string} formattedString - * - * @return {Array.|null} - */ - function getValuesFrom (formattedString) { - return formattedString.match(R_UNFORMATTED_VALUES); - } - - /*! - * @param {Object} easingObject - * @param {Object} tokenData - */ - function expandEasingObject (easingObject, tokenData) { - Tweenable.each(tokenData, function (prop) { - var currentProp = tokenData[prop]; - var chunkNames = currentProp.chunkNames; - var chunkLength = chunkNames.length; - var easingChunks = easingObject[prop].split(' '); - var lastEasingChunk = easingChunks[easingChunks.length - 1]; - - for (var i = 0; i < chunkLength; i++) { - easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk; - } + delete easingObject[prop]; + }); + } - delete easingObject[prop]; - }); - } + /*! + * @param {Object} easingObject + * @param {Object} tokenData + */ + function collapseEasingObject (easingObject, tokenData) { + Tweenable.each(tokenData, function (prop) { + var currentProp = tokenData[prop]; + var chunkNames = currentProp.chunkNames; + var chunkLength = chunkNames.length; + var composedEasingString = ''; + + for (var i = 0; i < chunkLength; i++) { + composedEasingString += ' ' + easingObject[chunkNames[i]]; + delete easingObject[chunkNames[i]]; + } - /*! - * @param {Object} easingObject - * @param {Object} tokenData - */ - function collapseEasingObject (easingObject, tokenData) { - Tweenable.each(tokenData, function (prop) { - var currentProp = tokenData[prop]; - var chunkNames = currentProp.chunkNames; - var chunkLength = chunkNames.length; - var composedEasingString = ''; - - for (var i = 0; i < chunkLength; i++) { - composedEasingString += ' ' + easingObject[chunkNames[i]]; - delete easingObject[chunkNames[i]]; - } + easingObject[prop] = composedEasingString.substr(1); + }); + } - easingObject[prop] = composedEasingString.substr(1); - }); + Tweenable.prototype.filter.token = { + 'tweenCreated': function (currentState, fromState, toState, easingObject) { + sanitizeObjectForHexProps(currentState); + sanitizeObjectForHexProps(fromState); + sanitizeObjectForHexProps(toState); + this._tokenData = getFormatManifests(currentState); + }, + + 'beforeTween': function (currentState, fromState, toState, easingObject) { + expandEasingObject(easingObject, this._tokenData); + expandFormattedProperties(currentState, this._tokenData); + expandFormattedProperties(fromState, this._tokenData); + expandFormattedProperties(toState, this._tokenData); + }, + + 'afterTween': function (currentState, fromState, toState, easingObject) { + collapseFormattedProperties(currentState, this._tokenData); + collapseFormattedProperties(fromState, this._tokenData); + collapseFormattedProperties(toState, this._tokenData); + collapseEasingObject(easingObject, this._tokenData); } + }; - Tweenable.prototype.filter.token = { - 'tweenCreated': function (currentState, fromState, toState, easingObject) { - sanitizeObjectForHexProps(currentState); - sanitizeObjectForHexProps(fromState); - sanitizeObjectForHexProps(toState); - this._tokenData = getFormatManifests(currentState); - }, - - 'beforeTween': function (currentState, fromState, toState, easingObject) { - expandEasingObject(easingObject, this._tokenData); - expandFormattedProperties(currentState, this._tokenData); - expandFormattedProperties(fromState, this._tokenData); - expandFormattedProperties(toState, this._tokenData); - }, - - 'afterTween': function (currentState, fromState, toState, easingObject) { - collapseFormattedProperties(currentState, this._tokenData); - collapseFormattedProperties(fromState, this._tokenData); - collapseFormattedProperties(toState, this._tokenData); - collapseEasingObject(easingObject, this._tokenData); - } - }; - - } (Tweenable)); + } (Tweenable)); - }(this, window)); + }(window)); return window.Tweenable; }); From 6d2e6bd88c640326569279eb326b3422cf0a137b Mon Sep 17 00:00:00 2001 From: Eldad Bercovici Date: Fri, 14 Nov 2014 16:49:53 +0200 Subject: [PATCH 109/159] Fix for #250 As pointed out in #250, in Angular 1.3 this throws an error. Since `oldSlides` isn't used anywhere I simply deleted it. --- src/directives/rn-carousel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 86d15a6..db3548f 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -434,7 +434,6 @@ scope[deepWatch?'$watch':'$watchCollection'](repeatCollection, function(newValue, oldValue) { //console.log('repeatCollection', currentSlides); - var oldSlides = (currentSlides || newValue).slice(); currentSlides = newValue; // if deepWatch ON ,manually compare objects to guess the new position if (deepWatch && angular.isArray(newValue)) { From ec82edc64ee33693ce0ca012af6f53b8a2b43ea8 Mon Sep 17 00:00:00 2001 From: Vincent Spallek Date: Thu, 11 Dec 2014 13:29:09 +0100 Subject: [PATCH 110/159] enabled controls so that they also work for a carousel that is not repeat based --- src/directives/rn-carousel.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index db3548f..47434b4 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -214,15 +214,6 @@ animating = false, locked = false; - if(iAttributes.rnCarouselControls!==undefined) { - // dont use a directive for this - var tpl = ''; - iElement.append($compile(angular.element(tpl))(scope)); - } - $swipe.bind(iElement, { start: swipeStart, move: swipeMove, @@ -359,6 +350,24 @@ angular.forEach(getSlidesDOM(), function(node, index) { currentSlides.push({id: index}); }); + + if(iAttributes.rnCarouselControls!==undefined) { + // dont use a directive for this + var tpl = ''; + iElement.append($compile(angular.element(tpl))(scope)); + } + } else { + if(iAttributes.rnCarouselControls!==undefined) { + // dont use a directive for this + var tpl = ''; + iElement.append($compile(angular.element(tpl))(scope)); + } } var autoSlider; From 76c135aecfba79bfd23b7faa93619c04aef9138d Mon Sep 17 00:00:00 2001 From: Vincent Spallek Date: Thu, 11 Dec 2014 17:31:47 +0100 Subject: [PATCH 111/159] Removed copied code --- src/directives/rn-carousel.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index 47434b4..aa517f2 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -350,24 +350,16 @@ angular.forEach(getSlidesDOM(), function(node, index) { currentSlides.push({id: index}); }); - - if(iAttributes.rnCarouselControls!==undefined) { - // dont use a directive for this - var tpl = ''; - iElement.append($compile(angular.element(tpl))(scope)); - } - } else { - if(iAttributes.rnCarouselControls!==undefined) { - // dont use a directive for this - var tpl = ''; - iElement.append($compile(angular.element(tpl))(scope)); - } + } + + if (iAttributes.rnCarouselControls!==undefined) { + // dont use a directive for this + var nextSlideIndexCompareValue = isRepeatBased ? repeatCollection + '.length - 1' : currentSlides.length - 1; + var tpl = ''; + iElement.append($compile(angular.element(tpl))(scope)); } var autoSlider; From c68bf6677b6614993c6c7195030776e0bc6e7862 Mon Sep 17 00:00:00 2001 From: Eoin Date: Mon, 15 Dec 2014 15:59:10 +0100 Subject: [PATCH 112/159] Disable swipe when there is only 1 item and move the locked check to drag start. --- src/directives/rn-carousel.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index db3548f..3c45638 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -206,7 +206,7 @@ destination, swipeMoved = false, //animOnIndexChange = true, - currentSlides, + currentSlides = [], elWidth = null, elX = null, animateTransitions = true, @@ -324,6 +324,9 @@ function swipeStart(coords, event) { // console.log('swipeStart', coords, event); + if (locked || currentSlides.length <= 1) { + return; + } $document.bind('mouseup', documentMouseUpEvent); updateContainerWidth(); elX = iElement[0].querySelector('li').getBoundingClientRect().left; @@ -334,9 +337,6 @@ function swipeMove(coords, event) { //console.log('swipeMove', coords, event); - if (locked) { - return; - } var x, delta; if (pressed) { x = coords.x; From 52497541a69e49ea38e6b9fb714144858b141c8d Mon Sep 17 00:00:00 2001 From: rob-clicktripz Date: Wed, 17 Dec 2014 22:29:41 -0800 Subject: [PATCH 113/159] added support for angular bindonce :: operator --- src/directives/rn-carousel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directives/rn-carousel.js b/src/directives/rn-carousel.js index ba49b0b..2a87e8a 100755 --- a/src/directives/rn-carousel.js +++ b/src/directives/rn-carousel.js @@ -354,7 +354,7 @@ if (iAttributes.rnCarouselControls!==undefined) { // dont use a directive for this - var nextSlideIndexCompareValue = isRepeatBased ? repeatCollection + '.length - 1' : currentSlides.length - 1; + var nextSlideIndexCompareValue = isRepeatBased ? repeatCollection.replace('::', '') + '.length - 1' : currentSlides.length - 1; var tpl = '
                  -

                  buffered ngRepeat with auto-slide and builtin indicators

                  +

                  buffered ngRepeat with auto-slide(pause on hover) and builtin indicators