├── .gitignore ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── swipe ├── swipe.html ├── swipe.css └── swipe.coffee ├── package.js ├── versions.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | *.DS_Store 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This project is not unmaintained. Please let me know if you'd like to maintain this project. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This project is not unmaintained. Please let me know if you'd like to maintain this project. -------------------------------------------------------------------------------- /swipe/swipe.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'ccorcos:swipe', 3 | summary: 'A package for creating apps that swipe between pages', 4 | version: '1.1.3', 5 | git: 'https://github.com/ccorcos/meteor-swipe.git' 6 | }); 7 | 8 | Package.onUse(function(api) { 9 | api.versionsFrom('1.0'); 10 | 11 | api.use(['templating', 'coffeescript'], 'client') 12 | 13 | api.addFiles(['swipe/swipe.html', 'swipe/swipe.coffee', 'swipe/swipe.css'], 'client'); 14 | 15 | api.export('Swipe', ['client']) 16 | 17 | }); 18 | 19 | // Package.onTest(function(api) { 20 | // api.use('tinytest'); 21 | // api.use('ccorcos:swipe'); 22 | // api.addFiles('ccorcos:swipe-tests.js'); 23 | // }); 24 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "base64", 5 | "1.0.1" 6 | ], 7 | [ 8 | "blaze", 9 | "2.0.3" 10 | ], 11 | [ 12 | "coffeescript", 13 | "1.0.4" 14 | ], 15 | [ 16 | "deps", 17 | "1.0.5" 18 | ], 19 | [ 20 | "ejson", 21 | "1.0.4" 22 | ], 23 | [ 24 | "geojson-utils", 25 | "1.0.1" 26 | ], 27 | [ 28 | "htmljs", 29 | "1.0.2" 30 | ], 31 | [ 32 | "id-map", 33 | "1.0.1" 34 | ], 35 | [ 36 | "jquery", 37 | "1.0.1" 38 | ], 39 | [ 40 | "json", 41 | "1.0.1" 42 | ], 43 | [ 44 | "meteor", 45 | "1.1.3" 46 | ], 47 | [ 48 | "minimongo", 49 | "1.0.5" 50 | ], 51 | [ 52 | "observe-sequence", 53 | "1.0.3" 54 | ], 55 | [ 56 | "ordered-dict", 57 | "1.0.1" 58 | ], 59 | [ 60 | "random", 61 | "1.0.1" 62 | ], 63 | [ 64 | "reactive-var", 65 | "1.0.3" 66 | ], 67 | [ 68 | "templating", 69 | "1.0.9" 70 | ], 71 | [ 72 | "tracker", 73 | "1.0.3" 74 | ], 75 | [ 76 | "underscore", 77 | "1.0.1" 78 | ] 79 | ], 80 | "pluginDependencies": [], 81 | "toolVersion": "meteor-tool@1.0.35", 82 | "format": "1.0" 83 | } -------------------------------------------------------------------------------- /swipe/swipe.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-touch-callout: none; 3 | -webkit-tap-highlight-color: rgba(0,0,0,0); 4 | } 5 | 6 | html{ 7 | width: 100%; 8 | height: 100%; 9 | overflow: hidden; 10 | } 11 | 12 | body{ 13 | width: 100%; 14 | height: 100%; 15 | position: relative; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | .pages { 21 | width: 100%; 22 | height: 100%; 23 | box-sizing: border-box; 24 | /* pointer-events: all; 25 | */} 26 | 27 | .page { 28 | box-sizing: border-box; 29 | width: 100%; 30 | height: 100%; 31 | position: absolute; 32 | top: 0; 33 | left: 0; 34 | 35 | -webkit-touch-callout: none; 36 | -webkit-user-select: none; 37 | -khtml-user-select: none; 38 | -moz-user-select: none; 39 | -ms-user-select: none; 40 | user-select: none; 41 | 42 | /*initially hidden*/ 43 | display: none; 44 | 45 | } 46 | 47 | .animate { 48 | transition: transform 0.3s ease-out; 49 | -webkit-transition: -webkit-transform 0.3s ease-out; 50 | } 51 | 52 | .scrollable { 53 | overflow-y: scroll; 54 | -webkit-overflow-scrolling: touch; 55 | } 56 | 57 | .swipe-control { 58 | /* pointer-events: none; 59 | */ cursor: pointer; 60 | -webkit-touch-callout: none; 61 | -webkit-user-select: none; 62 | -khtml-user-select: none; 63 | -moz-user-select: none; 64 | -ms-user-select: none; 65 | user-select: none; 66 | } 67 | 68 | .no-swipe { 69 | 70 | } 71 | 72 | .noselect { 73 | -webkit-touch-callout: none; 74 | -webkit-user-select: none; 75 | -khtml-user-select: none; 76 | -moz-user-select: none; 77 | -ms-user-select: none; 78 | user-select: none; 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meteor Swipe [MAINTAINER WANTED] 2 | 3 | This package comes with all the bells and whistles for creating an app with swiping between pages. Checkout [this repo for some examples](https://github.com/ccorcos/meteor-swipe-examples). 4 | 5 | ## Getting Started 6 | 7 | Add this package to your project: 8 | 9 | ``` 10 | meteor add ccorcos:swipe 11 | ``` 12 | 13 | Create some templates. And initialize a swiper with those template names. 14 | 15 | `Swiper = new Swipe(['page1', 'page2', 'page3', 'page4', 'page5'])` 16 | 17 | Insert the swiper somewhere and make sure to pass the swiper object. 18 | 19 | ``` 20 | 25 | ``` 26 | 27 | Don't forget the helper. 28 | 29 | ``` 30 | Template.main.helpers 31 | Swiper: -> Swiper 32 | ``` 33 | 34 | Control the layout of the pages by reactively setting the left and right 35 | pages. 36 | 37 | ``` 38 | Template.main.rendered = -> 39 | 40 | # initial page 41 | Swiper.setInitialPage('page1') 42 | 43 | # page control 44 | Tracker.autorun -> 45 | if Swiper.pageIs('page1') 46 | Swiper.leftRight(null, 'page2') 47 | 48 | Tracker.autorun -> 49 | if Swiper.pageIs('page2') 50 | Swiper.leftRight('page1', 'page3') 51 | 52 | Tracker.autorun -> 53 | if Swiper.pageIs('page3') 54 | Swiper.leftRight('page2', 'page4') 55 | 56 | 57 | Tracker.autorun -> 58 | if Swiper.pageIs('page4') 59 | Swiper.leftRight('page3', 'page5') 60 | 61 | Tracker.autorun -> 62 | if Swiper.pageIs('page5') 63 | Swiper.leftRight('page4', null) 64 | ``` 65 | 66 | `setInitialPage` sets the current page without any animation. 67 | 68 | To prevent a swipe from starting on a certain element, simply add a `no-swipe` 69 | class to that element. 70 | 71 | If you want to be able to click or touch an element within the swiper, you have 72 | to use the `click` function. This takes care of making sure that you 73 | touch up inside the element you intent to click. 74 | 75 | ``` 76 | Swiper.click 'page1', '.pop-up', (e,t) -> 77 | alert 'hey!' 78 | ``` 79 | 80 | And if you want to control control swiping, you'll need to set the "swipe-control" class 81 | ``` 82 | Swiper.click 'page1', '.next', (e,t) -> 83 | Swiper.moveRight() 84 | ``` 85 | 86 | Lastly, if you want to vertically scroll a div, use the `scrollable` class. 87 | 88 | 89 | ## Known Issues 90 | - Bugs out when the mouse drags off screen. 91 | - Can be abused in Safari with touches somehow. 92 | -------------------------------------------------------------------------------- /swipe/swipe.coffee: -------------------------------------------------------------------------------- 1 | 2 | print = (msg) -> 3 | if false 4 | console.log msg 5 | 6 | eventPrint = (msg) -> 7 | if false 8 | console.log msg 9 | 10 | debugPrint = (msg) -> 11 | if false 12 | console.log msg 13 | 14 | class Swipe 15 | constructor: (@templates, arrowKeys=true) -> 16 | # @templates is a list of template name strings that will be used by 17 | # the Swiper 18 | 19 | # Create a reactive dictionary so the current page can be a reactive variable 20 | @state = new Package['reactive-dict'].ReactiveDict() 21 | @state.set 'page', null 22 | # Handle the left and right pages manually. Otherwise every transition will trigger 23 | # multiple reactive autoruns 24 | @left = null 25 | @right = null 26 | # keep track of the previous page so we make make sure not to hide it so the 27 | # animations finish when the page drops. 28 | @previousPage = null 29 | # Keep track of the template this object is bound to so we can t.find specifically 30 | # within the template and manage template variables. 31 | # The template manages all the touch events and drag-swiping. The swiper manages 32 | # the pages. 33 | @t = null # template 34 | 35 | self = @ 36 | # When the window resizes, reposition the left and right 37 | $(window).resize -> 38 | # set the width of the page so the template knows where to position 39 | # the left and right pages 40 | self.t?.width = $(self.t?.find('.pages')).width() 41 | # do not animate the window resizing 42 | $(self.t.findAll('.animate')).removeClass('animate') 43 | # re-position the left and right pages. 44 | self.setLeft self.left 45 | self.setRight self.right 46 | 47 | # If we want to allow arrow keys to swipe, we need to register the arrow key 48 | # events 49 | if arrowKeys 50 | document.onkeydown = (e) -> 51 | if not e then e = window.event 52 | code = e.keyCode 53 | if code is 37 54 | event.preventDefault() 55 | # clear animations will immediately finish the previous animation 56 | # and moveLeft will execute the next animation 57 | self.clearAnimate() 58 | self.moveLeft() 59 | else if code is 39 60 | event.preventDefault() 61 | # clear animations will immediately finish the previous animation 62 | # and moveRight will execute the next animation 63 | self.clearAnimate() 64 | self.moveRight() 65 | 66 | clearAnimate: -> 67 | $(@t?.findAll('.animate')).removeClass('animate') 68 | 69 | animateAll: -> 70 | $(@t.findAll('.page')).addClass('animate') 71 | 72 | unanimate: (name) -> 73 | $(@t.find('.page.'+name)).removeClass('animate') 74 | 75 | animate: (name) -> 76 | $(@t.find('.page.'+name)).addClass('animate') 77 | 78 | animateRight: (name) -> 79 | $(@t.find('.page.'+name)).addClass('animate').css 'transform', 80 | 'translate3d('+@t.width+'px,0,0)' 81 | 82 | animateLeft: (name) -> 83 | $(@t.find('.page.'+name)).addClass('animate').css 'transform', 84 | 'translate3d(-'+@t.width+'px,0,0)' 85 | 86 | animateCenter: (name) -> 87 | $(@t.find('.page.'+name)).addClass('animate').css 'transform', 88 | 'translate3d(0px,0,0)' 89 | 90 | # set position regardless of animation 91 | displayRight: (name) -> 92 | $(@t.find('.page.'+name)).css('display', 'block').css 'transform', 93 | 'translate3d('+@t.width+'px,0,0)' 94 | 95 | displayLeft: (name) -> 96 | $(@t.find('.page.'+name)).css('display', 'block').css 'transform', 97 | 'translate3d(-'+@t.width+'px,0,0)' 98 | 99 | displayCenter: (name) -> 100 | $(@t.find('.page.'+name)).css('display', 'block').css 'transform', 101 | 'translate3d(0px,0,0)' 102 | 103 | transitionRight: (name) -> 104 | print "transitionRight" 105 | @hidePage @previousPage 106 | @clearAnimate() 107 | # @hideAllBut @getPage(), name 108 | @setRight name 109 | self = @ 110 | delay 0, -> 111 | self.moveRight() 112 | 113 | transitionLeft: (name) -> 114 | print "transitionLeft" 115 | @hidePage @previousPage 116 | @clearAnimate() 117 | # @hideAllBut @getPage(), name 118 | @setLeft name 119 | self = @ 120 | delay 0, -> 121 | self.moveLeft() 122 | 123 | moveLeft: -> 124 | if @left 125 | print "moveLeft" 126 | @hideAllBut @getPage(), @left 127 | @unanimate @right 128 | # only animate the center and the left towards the right 129 | @animateRight @getPage() 130 | @animateCenter @left 131 | @setPage @left 132 | 133 | moveRight: -> 134 | if @right 135 | print "moveRight" 136 | @hideAllBut @getPage(), @right 137 | @unanimate @left 138 | # only animate the center and the left towards the right 139 | @animateLeft @getPage() 140 | @animateCenter @right 141 | @setPage @right 142 | 143 | setPage: (name) -> 144 | # this method will simply trigger any functions that autorun reactively on 145 | # the current page. This assumes whatever function is calling it will 146 | # take cre of any animations or transitions. 147 | @previousPage = @getPage() 148 | @state.set 'page', name 149 | 150 | hideAllBut: (names...) -> 151 | for n in _.partial(_.without, @templates).apply(this, names) 152 | @hidePage n 153 | 154 | hidePage: (name) -> 155 | $(@t.find('.page.'+name)).css('display', 'none') 156 | 157 | setInitialPage: (name) -> 158 | # hide everything when placing the initial page 159 | # the left and right should be unhidden later. 160 | for n in @templates 161 | if n isnt name then @hidePage n 162 | @setPage name 163 | # place this page in the center 164 | @displayCenter name 165 | 166 | setTemplate: (t) -> 167 | @t = t 168 | 169 | getPage: () -> 170 | @state.get 'page' 171 | 172 | pageIs: (name) -> 173 | # used as a reactive binding in an autorun to manage left and right pages 174 | @state.equals 'page', name 175 | 176 | setLeft: (name) -> 177 | @left = name 178 | @displayLeft name 179 | 180 | setRight: (name) -> 181 | @right = name 182 | @displayRight name 183 | 184 | drag: (posX) -> 185 | width = @t.width 186 | 187 | # Cant scroll in the direction where there is no page! 188 | if @left 189 | # positive posx reveals left 190 | posX = Math.min(width, posX) 191 | else 192 | posX = Math.min(0, posX) 193 | 194 | if @right 195 | # negative posx reveals right 196 | posX = Math.max(-width, posX) 197 | else 198 | posX = Math.max(0, posX) 199 | 200 | # update the page positions 201 | if @left 202 | $(@t.find('.page.'+@left)).css 'transform', 203 | 'translate3d(-' + (width - posX) + 'px,0,0)' 204 | if @right 205 | $(@t.find('.page.'+@right)).css 'transform', 206 | 'translate3d(' + (width + posX) + 'px,0,0)' 207 | 208 | $(@t.find('.page.'+@getPage())).css 'transform', 209 | 'translate3d(' + posX + 'px,0,0)' 210 | 211 | animateBack: () -> 212 | # Animate all pages back into place 213 | @animate @left 214 | @animate @right 215 | @animate @getPage() 216 | 217 | if @left 218 | $(@t.find('.page.'+@left)).css 'transform', 219 | 'translate3d(-' + @t.width + 'px,0,0)' 220 | 221 | if @right 222 | $(@t.find('.page.'+@right)).css 'transform', 223 | 'translate3d(' + @t.width + 'px,0,0)' 224 | 225 | $(@t.find('.page.'+@getPage())).css 'transform', 226 | 'translate3d(0px,0,0)' 227 | 228 | leftRight: (left, right) -> 229 | debugPrint 'leftRight' 230 | center = @getPage() 231 | @setLeft left 232 | @setRight right 233 | 234 | # dont hide the old center to give it time to animate offscreen just in case 235 | # it is removed. 236 | dontHide = [left, center, right, @previousPage] 237 | hideThese = _.difference(@templates, dontHide) 238 | 239 | for name in hideThese 240 | @hidePage name 241 | 242 | 243 | shouldControl: -> 244 | # don't register a click if the page is scrolled or being flicked. 245 | if @t.scrolling then return false 246 | speedX = 10*@t.velX 247 | flickX = @t.changeX + speedX 248 | speedY = 10*@t.velY 249 | flickY = @t.changeY + speedY 250 | Xok = Math.abs(flickX) <= 30 or Math.abs(@t.changeX) <= 10 251 | Yok = Math.abs(flickY) <= 30 or Math.abs(@t.changeY) <= 10 252 | return Xok and Yok 253 | 254 | 255 | # These are effectively the same: 256 | 257 | # click Swiper, 'page1', '.next', (e,t) -> 258 | # Swiper.moveRight() 259 | 260 | # Template.page1.events 261 | # 'mouseup .next': (e,t) -> 262 | # console.log e 263 | # Swiper.moveRight() 264 | # 265 | # 'touchend .next': (e,t) -> 266 | # if e.currentTarget is Swiper.element 267 | # Swiper.moveRight() 268 | 269 | click: (template, selector, handler) -> 270 | Swiper = @ 271 | mouseup = 'mouseup ' + selector 272 | touchend = 'touchend ' + selector 273 | eventMap = {} 274 | 275 | eventMap[mouseup] = (e,t) -> 276 | if Swiper.shouldControl() and not Swiper.t.touchDown 277 | eventPrint "mouseup control" 278 | handler.bind(@)(e,t) 279 | 280 | eventMap[touchend] = (e,t) -> 281 | if e.currentTarget is Swiper.element and Swiper.shouldControl() 282 | eventPrint "touchend control" 283 | e.stopPropagation() 284 | handler.bind(@)(e,t) 285 | 286 | t = Template[template] 287 | if t 288 | t.events eventMap 289 | else 290 | console.log "WARNING: Template '" + template + "' not found." 291 | 292 | 293 | 294 | 295 | # register the page names to dynamically render each page 296 | Template.swipe.helpers 297 | pageNames: -> _.map @Swiper?.templates, (name) -> {name: name} 298 | 299 | 300 | Template.swipe.rendered = -> 301 | # check that templates is passed 302 | if not @data.Swiper 303 | console.log("ERROR: must pass a Swipe object.") 304 | else 305 | # Bind the Swiper to this template and the template to the swiper 306 | @Swiper = @data.Swiper 307 | @Swiper.setTemplate(@) 308 | 309 | # keep track of the width so we know where to place pages to the left 310 | # and the right 311 | @width = $(@find('.pages')).width() 312 | 313 | # keep track of scrolling 314 | @mouseDown = false 315 | @touchDown = false 316 | @startX = 0 317 | @mouseX = 0 318 | @posX = 0 319 | @startY = 0 320 | @mouseY = 0 321 | @posY = 0 322 | 323 | # We need to keep track of whether the user is scrolling or swiping. 324 | @scrollableCSS = false 325 | @mightBeScrolling = false 326 | @scrolling = false 327 | 328 | 329 | targetInClass = (name, target) -> 330 | $(target).hasClass(name) or $(target).parentsUntil('body', '.' + name).length 331 | 332 | Template.swipe.events 333 | 'mousedown .pages': (e,t) -> 334 | # if we're the user has already touched down, we want to ignore mouse events 335 | if t.touchDown 336 | return true 337 | 338 | eventPrint "mousedown" 339 | noSwipeCSS = targetInClass 'no-swipe', e.target 340 | 341 | unless noSwipeCSS 342 | # remove stop all animations in this swiper 343 | t.Swiper.clearAnimate() 344 | clickX = e.pageX 345 | clickY = e.pageY 346 | 347 | t.startX = clickX # beginning of the swipe 348 | t.mouseX = clickX # current position of the swipe 349 | t.startY = clickY # beginning of the swipe 350 | t.mouseY = clickY # current position of the swipe 351 | t.mouseDown = true # click swipe has begun 352 | t.touchDown = false 353 | 354 | return true 355 | 356 | 'touchstart .pages': (e,t) -> 357 | eventPrint "touchstart" 358 | 359 | noSwipeCSS = targetInClass 'no-swipe', e.target 360 | scrollableCSS = targetInClass 'scrollable', e.target 361 | 362 | # Check to see if the user touched inside of a scrollable div. If so, 363 | # then the user might be scrolling depending on whether he moves his finger 364 | # to the side to swipe or up and down to scroll. Once we have determined the 365 | # direction of the gesture, we can be certain of whether the user is scrolling 366 | # or not. 367 | if scrollableCSS 368 | t.scrollableCSS = true 369 | t.mightBeScrolling = true 370 | t.scrolling = false 371 | else 372 | t.scrollableCSS = false 373 | t.mightBeScrolling = false 374 | t.scrolling = false 375 | 376 | unless noSwipeCSS 377 | # keep track of what element the pointer is over for touchend 378 | x = e.originalEvent.touches[0].pageX - window.pageXOffset 379 | y = e.originalEvent.touches[0].pageY - window.pageYOffset 380 | target = document.elementFromPoint(x, y) 381 | t.Swiper.element = target 382 | 383 | # remove stop all animations in this swiper 384 | t.Swiper.clearAnimate() 385 | # key track of Y for calculating scroll 386 | clickX = e.originalEvent.touches[0].pageX 387 | clickY = e.originalEvent.touches[0].pageY 388 | t.startX = clickX # beginning of the swipe 389 | t.mouseX = clickX # current position of the swipe 390 | t.startY = clickY # beginning of the swipe 391 | t.mouseY = clickY # current position of the swipe 392 | # we must distinguish between mouse and touch because sometimes 393 | # touch will induce a click; touchend => mouseup 394 | t.mouseDown = false 395 | t.touchDown = true 396 | 397 | return true 398 | 399 | 'mousemove .pages': (e,t) -> 400 | # if the mouse is pressed, we need to keep track of the swipe. 401 | # note that you cannot scroll by clicking the mouse! 402 | if t.mouseDown 403 | eventPrint "mousemove" 404 | newMouseX = e.pageX 405 | oldMouseX = t.mouseX 406 | t.velX = newMouseX - oldMouseX 407 | t.changeX = newMouseX - t.startX 408 | posX = t.changeX + t.posX 409 | t.mouseX = newMouseX 410 | 411 | newMouseY = e.pageY 412 | oldMouseY = t.mouseY 413 | t.velY = newMouseY - oldMouseY 414 | t.changeY = newMouseY - t.startY 415 | posY = t.changeY + t.posY 416 | t.mouseY = newMouseY 417 | 418 | t.Swiper.drag(posX) 419 | 420 | return true 421 | 422 | 'touchmove .pages': (e,t) -> 423 | eventPrint "touchmove" 424 | noSwipeCSS = targetInClass 'no-swipe', e.target 425 | 426 | # If we're not sure if the user is scrolling or not, then we need to check to 427 | # see if the first motion is left-right, or up-down. 428 | if t.mightBeScrolling 429 | # keep track of what element the pointer is over for touchend 430 | x = e.originalEvent.touches[0].pageX - window.pageXOffset 431 | y = e.originalEvent.touches[0].pageY - window.pageYOffset 432 | target = document.elementFromPoint(x, y) 433 | t.Swiper.element = target 434 | 435 | newMouseX = e.originalEvent.touches[0].pageX 436 | oldMouseX = t.mouseX 437 | t.velX = newMouseX - oldMouseX 438 | t.changeX = newMouseX - t.startX 439 | posX = t.changeX + t.posX 440 | t.mouseX = newMouseX 441 | 442 | newMouseY = e.originalEvent.touches[0].pageY 443 | oldMouseY = t.mouseY 444 | t.velY = newMouseY - oldMouseY 445 | t.changeY = newMouseY - t.startY 446 | posY = t.changeY + t.posY 447 | t.mouseY = newMouseY 448 | 449 | speedX = 10*t.velX 450 | flickX = t.changeX + speedX 451 | 452 | speedY = 10*t.velY 453 | flickY = t.changeY + speedY 454 | 455 | # compute the relative angles of up-down or left-right 456 | if Math.abs(flickY*1.66) > Math.abs(flickX) 457 | # we've determined that the user is definitely scrolling 458 | # so we don't want to compute this all over again. on the next 459 | # touchmove, just compute the scroll position. 460 | t.mightBeScrolling = false 461 | t.scrolling = true 462 | return true 463 | else 464 | # if the user is swiping, not scrolling, we can set the appropriate values 465 | t.mightBeScrolling = false 466 | t.scrolling = false 467 | if noSwipeCSS 468 | # if you 469 | return true 470 | else 471 | # prevent the default scrolling functionality 472 | e.preventDefault() 473 | t.Swiper.drag(posX) 474 | return false 475 | else if t.scrolling 476 | # if we know the user is scrolling, we can just let the default 477 | # functionality handle it. 478 | return true 479 | else 480 | unless noSwipeCSS 481 | # if the user is swiping, then we need to prevent the default functionality 482 | # of scrolling. 483 | e.preventDefault() 484 | 485 | # keep track of what element the pointer is over for touchend 486 | x = e.originalEvent.touches[0].pageX - window.pageXOffset 487 | y = e.originalEvent.touches[0].pageY - window.pageYOffset 488 | target = document.elementFromPoint(x, y) 489 | t.Swiper.element = target 490 | 491 | newMouseX = e.originalEvent.touches[0].pageX 492 | oldMouseX = t.mouseX 493 | t.velX = newMouseX - oldMouseX 494 | t.changeX = newMouseX - t.startX 495 | posX = t.changeX + t.posX 496 | t.mouseX = newMouseX 497 | 498 | # keep track of y, so we know if the `shouldControl` and we can measure both 499 | # x and y directions. 500 | newMouseY = e.originalEvent.touches[0].pageY 501 | oldMouseY = t.mouseY 502 | t.velY = newMouseY - oldMouseY 503 | t.changeY = newMouseY - t.startY 504 | posY = t.changeY + t.posY 505 | t.mouseY = newMouseY 506 | 507 | t.Swiper.drag(posX) 508 | return false 509 | 510 | 'mouseup .pages': (e,t) -> 511 | 512 | if t.mouseDown 513 | eventPrint "mouseup" 514 | posX = t.changeX + t.posX 515 | momentum = Math.abs(10*t.velX) 516 | momentum = Math.min(momentum, t.width/2) 517 | momentum = momentum*sign(t.velX) 518 | distance = posX + momentum 519 | swipeControlCSS = targetInClass 'swipe-control', e.target 520 | # run the swiping event 521 | if swipeControlCSS and (e.target is t.Swiper.element) and t.Swiper.shouldControl() 522 | t.velX = 0 523 | t.startX = 0 524 | t.mouseX = 0 525 | t.changeX = 0 526 | t.velY = 0 527 | t.startY = 0 528 | t.mouseY = 0 529 | t.changeY = 0 530 | t.mouseDown = false 531 | return 532 | 533 | # otherwise, snap the page where it should go 534 | index = Math.round(distance / t.width) 535 | if index is -1 536 | t.Swiper.moveRight() 537 | else if index is 1 538 | t.Swiper.moveLeft() 539 | else 540 | t.Swiper.animateBack() 541 | 542 | t.velX = 0 543 | t.startX = 0 544 | t.mouseX = 0 545 | t.changeX = 0 546 | t.velY = 0 547 | t.startY = 0 548 | t.mouseY = 0 549 | t.changeY = 0 550 | t.mouseDown = false 551 | 552 | 'touchend .pages': (e,t) -> 553 | if t.touchDown 554 | eventPrint "touchend" 555 | 556 | posX = t.changeX + t.posX 557 | momentum = Math.abs(10*t.velX) 558 | momentum = Math.min(momentum, t.width/2) 559 | momentum = momentum*sign(t.velX) 560 | distance = posX + momentum 561 | 562 | swipeControlCSS = targetInClass 'swipe-control', e.target 563 | # run the swiping event 564 | if swipeControlCSS and (e.target is t.Swiper.element) and t.Swiper.shouldControl() 565 | t.velX = 0 566 | t.startX = 0 567 | t.mouseX = 0 568 | t.changeX = 0 569 | t.velY = 0 570 | t.startY = 0 571 | t.mouseY = 0 572 | t.changeY = 0 573 | t.touchDown = false 574 | return true 575 | 576 | index = Math.round(distance / t.width) 577 | if index is -1 578 | t.Swiper.moveRight() 579 | else if index is 1 580 | t.Swiper.moveLeft() 581 | else 582 | t.Swiper.animateBack() 583 | 584 | t.velX = 0 585 | t.startX = 0 586 | t.mouseX = 0 587 | t.changeX = 0 588 | t.velY = 0 589 | t.startY = 0 590 | t.mouseY = 0 591 | t.changeY = 0 592 | t.touchDown = false 593 | return true 594 | 595 | 596 | sign = (x) -> 597 | if x >= 0 then return 1 else return -1 598 | 599 | bound = (min, max, n) -> 600 | Math.min(Math.max(min, n), max) 601 | 602 | wrap = (min, max, n) -> 603 | if n < min 604 | return max - (min - 1) - 1 605 | else if n > max 606 | return min + (n - max) - 1 607 | else 608 | return n 609 | 610 | 611 | delay = (ms, func) -> setTimeout func, ms 612 | --------------------------------------------------------------------------------