| OLD | NEW |
| 1 <!-- | 1 <!-- |
| 2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | 2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
| 3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 6 Code distributed by Google as part of the polymer project is also | 6 Code distributed by Google as part of the polymer project is also |
| 7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 8 --> | 8 --> |
| 9 | 9 |
| 10 <link rel="import" href="../polymer/polymer.html"> |
| 11 <link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html
"> |
| 12 |
| 10 <!-- | 13 <!-- |
| 11 `paper-ripple` provides a visual effect that other paper elements can | 14 `paper-ripple` provides a visual effect that other paper elements can |
| 12 use to simulate a rippling effect emanating from the point of contact. The | 15 use to simulate a rippling effect emanating from the point of contact. The |
| 13 effect can be visualized as a concentric circle with motion. | 16 effect can be visualized as a concentric circle with motion. |
| 14 | 17 |
| 15 Example: | 18 Example: |
| 16 | 19 |
| 17 <paper-ripple></paper-ripple> | 20 <paper-ripple></paper-ripple> |
| 18 | 21 |
| 19 `paper-ripple` listens to "mousedown" and "mouseup" events so it would display r
ipple | 22 `paper-ripple` listens to "mousedown" and "mouseup" events so it would display r
ipple |
| 20 effect when touches on it. You can also defeat the default behavior and | 23 effect when touches on it. You can also defeat the default behavior and |
| 21 manually route the down and up actions to the ripple element. Note that it is | 24 manually route the down and up actions to the ripple element. Note that it is |
| 22 important if you call mousedownAction() you will have to make sure to call | 25 important if you call downAction() you will have to make sure to call |
| 23 mouseupAction() so that `paper-ripple` would end the animation loop. | 26 upAction() so that `paper-ripple` would end the animation loop. |
| 24 | 27 |
| 25 Example: | 28 Example: |
| 26 | 29 |
| 27 <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> | 30 <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> |
| 28 ... | 31 ... |
| 29 downAction: function(e) { | 32 downAction: function(e) { |
| 30 this.$.ripple.mousedownAction({x: e.x, y: e.y}); | 33 this.$.ripple.downAction({x: e.x, y: e.y}); |
| 31 }, | 34 }, |
| 32 upAction: function(e) { | 35 upAction: function(e) { |
| 33 this.$.ripple.mouseupAction(); | 36 this.$.ripple.upAction(); |
| 34 } | 37 } |
| 35 | 38 |
| 36 Styling ripple effect: | 39 Styling ripple effect: |
| 37 | 40 |
| 38 Use CSS color property to style the ripple: | 41 Use CSS color property to style the ripple: |
| 39 | 42 |
| 40 paper-ripple { | 43 paper-ripple { |
| 41 color: #4285f4; | 44 color: #4285f4; |
| 42 } | 45 } |
| 43 | 46 |
| 44 Note that CSS color property is inherited so it is not required to set it on | 47 Note that CSS color property is inherited so it is not required to set it on |
| 45 the `paper-ripple` element directly. | 48 the `paper-ripple` element directly. |
| 46 | 49 |
| 47 By default, the ripple is centered on the point of contact. Apply the `recenter
s` | 50 By default, the ripple is centered on the point of contact. Apply the `recenter
s` |
| 48 attribute to have the ripple grow toward the center of its container. | 51 attribute to have the ripple grow toward the center of its container. |
| 49 | 52 |
| 50 <paper-ripple recenters></paper-ripple> | 53 <paper-ripple recenters></paper-ripple> |
| 51 | 54 |
| 55 You can also center the ripple inside its container from the start. |
| 56 |
| 57 <paper-ripple center></paper-ripple> |
| 58 |
| 52 Apply `circle` class to make the rippling effect within a circle. | 59 Apply `circle` class to make the rippling effect within a circle. |
| 53 | 60 |
| 54 <paper-ripple class="circle"></paper-ripple> | 61 <paper-ripple class="circle"></paper-ripple> |
| 55 | 62 |
| 56 @group Paper Elements | 63 @group Paper Elements |
| 57 @element paper-ripple | 64 @element paper-ripple |
| 58 @homepage github.io | 65 @hero hero.svg |
| 66 @demo demo/index.html |
| 59 --> | 67 --> |
| 60 | 68 |
| 61 <!-- | 69 <dom-module id="paper-ripple"> |
| 62 Fired when the animation finishes. This is useful if you want to wait until the
ripple | |
| 63 animation finishes to perform some action. | |
| 64 | 70 |
| 65 @event transitionend | 71 <!-- |
| 66 @param {Object} detail | 72 Fired when the animation finishes. This is useful if you want to wait until th
e ripple |
| 67 @param {Object} detail.node The animated node | 73 animation finishes to perform some action. |
| 68 --> | |
| 69 | 74 |
| 70 <link rel="import" href="../polymer/polymer.html"> | 75 @event transitionend |
| 76 @param {Object} detail |
| 77 @param {Object} detail.node The animated node |
| 78 --> |
| 71 | 79 |
| 72 <dom-module id="paper-ripple"> | |
| 73 <style> | 80 <style> |
| 74 :host { | 81 :host { |
| 75 display: block; | 82 display: block; |
| 76 position: absolute; | 83 position: absolute; |
| 77 border-radius: inherit; | 84 border-radius: inherit; |
| 78 overflow: hidden; | 85 overflow: hidden; |
| 79 top: 0; | 86 top: 0; |
| 80 left: 0; | 87 left: 0; |
| 81 right: 0; | 88 right: 0; |
| 82 bottom: 0; | 89 bottom: 0; |
| 90 } |
| 83 | 91 |
| 84 /* This resolves a rendering issue in Chrome 40 where the | 92 :host([animating]) { |
| 93 /* This resolves a rendering issue in Chrome (as of 40) where the |
| 85 ripple is not properly clipped by its parent (which may have | 94 ripple is not properly clipped by its parent (which may have |
| 86 rounded corners. See: http://jsbin.com/temexa/4 */ | 95 rounded corners). See: http://jsbin.com/temexa/4 |
| 96 |
| 97 Note: We only apply this style conditionally. Otherwise, the browser |
| 98 will create a new compositing layer for every ripple element on the |
| 99 page, and that would be bad. */ |
| 87 -webkit-transform: translate(0, 0); | 100 -webkit-transform: translate(0, 0); |
| 88 transform: translate3d(0, 0, 0); | 101 transform: translate3d(0, 0, 0); |
| 89 } | 102 } |
| 90 | 103 |
| 91 :host([noink]) { | 104 :host([noink]) { |
| 92 pointer-events: none; | 105 pointer-events: none; |
| 93 } | 106 } |
| 94 | 107 |
| 95 #background, | 108 #background, |
| 96 #waves, | 109 #waves, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 this.resetInteractionState(); | 225 this.resetInteractionState(); |
| 213 } | 226 } |
| 214 | 227 |
| 215 Ripple.MAX_RADIUS = 300; | 228 Ripple.MAX_RADIUS = 300; |
| 216 | 229 |
| 217 Ripple.prototype = { | 230 Ripple.prototype = { |
| 218 get recenters() { | 231 get recenters() { |
| 219 return this.element.recenters; | 232 return this.element.recenters; |
| 220 }, | 233 }, |
| 221 | 234 |
| 235 get center() { |
| 236 return this.element.center; |
| 237 }, |
| 238 |
| 222 get mouseDownElapsed() { | 239 get mouseDownElapsed() { |
| 223 var elapsed; | 240 var elapsed; |
| 224 | 241 |
| 225 if (!this.mouseDownStart) { | 242 if (!this.mouseDownStart) { |
| 226 return 0; | 243 return 0; |
| 227 } | 244 } |
| 228 | 245 |
| 229 elapsed = Utility.now() - this.mouseDownStart; | 246 elapsed = Utility.now() - this.mouseDownStart; |
| 230 | 247 |
| 231 if (this.mouseUpStart) { | 248 if (this.mouseUpStart) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 | 385 |
| 369 | 386 |
| 370 // 2d transform for safari because of border-radius and overflow:hidden
clipping bug. | 387 // 2d transform for safari because of border-radius and overflow:hidden
clipping bug. |
| 371 // https://bugs.webkit.org/show_bug.cgi?id=98538 | 388 // https://bugs.webkit.org/show_bug.cgi?id=98538 |
| 372 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' +
dy + 'px)'; | 389 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' +
dy + 'px)'; |
| 373 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy +
'px, 0)'; | 390 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy +
'px, 0)'; |
| 374 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; | 391 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; |
| 375 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; | 392 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; |
| 376 }, | 393 }, |
| 377 | 394 |
| 378 mousedownAction: function(event) { | 395 downAction: function(event) { |
| 396 var xCenter = this.containerMetrics.width / 2; |
| 397 var yCenter = this.containerMetrics.height / 2; |
| 398 |
| 379 this.resetInteractionState(); | 399 this.resetInteractionState(); |
| 380 this.mouseDownStart = Utility.now(); | 400 this.mouseDownStart = Utility.now(); |
| 381 | 401 |
| 382 this.xStart = event ? | 402 if (this.center) { |
| 383 event.x - this.containerMetrics.boundingRect.left : | 403 this.xStart = xCenter; |
| 384 this.containerMetrics.width / 2; | 404 this.yStart = yCenter; |
| 385 this.yStart = event ? | |
| 386 event.y - this.containerMetrics.boundingRect.top : | |
| 387 this.containerMetrics.height / 2; | |
| 388 | |
| 389 if (this.recenters) { | |
| 390 this.xEnd = this.containerMetrics.width / 2; | |
| 391 this.yEnd = this.containerMetrics.height / 2; | |
| 392 this.slideDistance = Utility.distance( | 405 this.slideDistance = Utility.distance( |
| 393 this.xStart, this.yStart, this.xEnd, this.yEnd | 406 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 394 ); | 407 ); |
| 408 } else { |
| 409 this.xStart = event ? |
| 410 event.detail.x - this.containerMetrics.boundingRect.left : |
| 411 this.containerMetrics.width / 2; |
| 412 this.yStart = event ? |
| 413 event.detail.y - this.containerMetrics.boundingRect.top : |
| 414 this.containerMetrics.height / 2; |
| 415 } |
| 416 |
| 417 if (this.recenters) { |
| 418 this.xEnd = xCenter; |
| 419 this.yEnd = yCenter; |
| 420 this.slideDistance = Utility.distance( |
| 421 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 422 ); |
| 395 } | 423 } |
| 396 | 424 |
| 397 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( | 425 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( |
| 398 this.xStart, | 426 this.xStart, |
| 399 this.yStart | 427 this.yStart |
| 400 ); | 428 ); |
| 401 | 429 |
| 402 this.waveContainer.style.top = | 430 this.waveContainer.style.top = |
| 403 (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'
; | 431 (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'
; |
| 404 this.waveContainer.style.left = | 432 this.waveContainer.style.left = |
| 405 (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; | 433 (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; |
| 406 | 434 |
| 407 this.waveContainer.style.width = this.containerMetrics.size + 'px'; | 435 this.waveContainer.style.width = this.containerMetrics.size + 'px'; |
| 408 this.waveContainer.style.height = this.containerMetrics.size + 'px'; | 436 this.waveContainer.style.height = this.containerMetrics.size + 'px'; |
| 409 }, | 437 }, |
| 410 | 438 |
| 411 mouseupAction: function(event) { | 439 upAction: function(event) { |
| 412 if (!this.isMouseDown) { | 440 if (!this.isMouseDown) { |
| 413 return; | 441 return; |
| 414 } | 442 } |
| 415 | 443 |
| 416 this.mouseUpStart = Utility.now(); | 444 this.mouseUpStart = Utility.now(); |
| 417 }, | 445 }, |
| 418 | 446 |
| 419 remove: function() { | 447 remove: function() { |
| 420 Polymer.dom(this.waveContainer.parentNode).removeChild( | 448 Polymer.dom(this.waveContainer.parentNode).removeChild( |
| 421 this.waveContainer | 449 this.waveContainer |
| 422 ); | 450 ); |
| 423 } | 451 } |
| 424 }; | 452 }; |
| 425 | 453 |
| 426 Polymer({ | 454 Polymer({ |
| 427 is: 'paper-ripple', | 455 is: 'paper-ripple', |
| 428 | 456 |
| 457 behaviors: [ |
| 458 Polymer.IronA11yKeysBehavior |
| 459 ], |
| 460 |
| 429 properties: { | 461 properties: { |
| 430 /** | 462 /** |
| 431 * The initial opacity set on the wave. | 463 * The initial opacity set on the wave. |
| 432 * | 464 * |
| 433 * @attribute initialOpacity | 465 * @attribute initialOpacity |
| 434 * @type number | 466 * @type number |
| 435 * @default 0.25 | 467 * @default 0.25 |
| 436 */ | 468 */ |
| 437 initialOpacity: { | 469 initialOpacity: { |
| 438 type: Number, | 470 type: Number, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 458 * @attribute recenters | 490 * @attribute recenters |
| 459 * @type boolean | 491 * @type boolean |
| 460 * @default false | 492 * @default false |
| 461 */ | 493 */ |
| 462 recenters: { | 494 recenters: { |
| 463 type: Boolean, | 495 type: Boolean, |
| 464 value: false | 496 value: false |
| 465 }, | 497 }, |
| 466 | 498 |
| 467 /** | 499 /** |
| 500 * If true, ripples will center inside its container |
| 501 * |
| 502 * @attribute recenters |
| 503 * @type boolean |
| 504 * @default false |
| 505 */ |
| 506 center: { |
| 507 type: Boolean, |
| 508 value: false |
| 509 }, |
| 510 |
| 511 /** |
| 468 * A list of the visual ripples. | 512 * A list of the visual ripples. |
| 469 * | 513 * |
| 470 * @attribute ripples | 514 * @attribute ripples |
| 471 * @type Array | 515 * @type Array |
| 472 * @default [] | 516 * @default [] |
| 473 */ | 517 */ |
| 474 ripples: { | 518 ripples: { |
| 475 type: Array, | 519 type: Array, |
| 476 value: function() { | 520 value: function() { |
| 477 return []; | 521 return []; |
| 478 } | 522 } |
| 479 }, | 523 }, |
| 480 | 524 |
| 525 /** |
| 526 * True when there are visible ripples animating within the |
| 527 * element. |
| 528 */ |
| 529 animating: { |
| 530 type: Boolean, |
| 531 readOnly: true, |
| 532 reflectToAttribute: true, |
| 533 value: false |
| 534 }, |
| 535 |
| 536 /** |
| 537 * If true, the ripple will remain in the "down" state until `holdDown` |
| 538 * is set to false again. |
| 539 */ |
| 540 holdDown: { |
| 541 type: Boolean, |
| 542 value: false, |
| 543 observer: '_holdDownChanged' |
| 544 }, |
| 545 |
| 481 _animating: { | 546 _animating: { |
| 482 type: Boolean | 547 type: Boolean |
| 483 }, | 548 }, |
| 484 | 549 |
| 485 _boundAnimate: { | 550 _boundAnimate: { |
| 486 type: Function, | 551 type: Function, |
| 487 value: function() { | 552 value: function() { |
| 488 return this.animate.bind(this); | 553 return this.animate.bind(this); |
| 489 } | 554 } |
| 490 }, | |
| 491 | |
| 492 _boundMousedownAction: { | |
| 493 type: Function, | |
| 494 value: function() { | |
| 495 return this.mousedownAction.bind(this); | |
| 496 } | |
| 497 }, | |
| 498 | |
| 499 _boundMouseupAction: { | |
| 500 type: Function, | |
| 501 value: function() { | |
| 502 return this.mouseupAction.bind(this); | |
| 503 } | |
| 504 } | 555 } |
| 505 }, | 556 }, |
| 506 | 557 |
| 507 get target () { | 558 get target () { |
| 508 return this.host || this.parentNode; | 559 var ownerRoot = Polymer.dom(this).getOwnerRoot(); |
| 560 var target; |
| 561 |
| 562 if (ownerRoot) { |
| 563 target = ownerRoot.host; |
| 564 } |
| 565 |
| 566 if (!target) { |
| 567 target = this.parentNode; |
| 568 } |
| 569 |
| 570 return target; |
| 571 }, |
| 572 |
| 573 keyBindings: { |
| 574 'enter:keydown': '_onEnterKeydown', |
| 575 'space:keydown': '_onSpaceKeydown', |
| 576 'space:keyup': '_onSpaceKeyup' |
| 509 }, | 577 }, |
| 510 | 578 |
| 511 attached: function() { | 579 attached: function() { |
| 512 this.target.addEventListener('mousedown', this._boundMousedownAction); | 580 this._listen(this.target, 'up', this.upAction.bind(this)); |
| 513 this.target.addEventListener('mouseup', this._boundMouseupAction); | 581 this._listen(this.target, 'down', this.downAction.bind(this)); |
| 582 |
| 583 if (!this.target.hasAttribute('noink')) { |
| 584 this.keyEventTarget = this.target; |
| 585 } |
| 514 }, | 586 }, |
| 515 | 587 |
| 516 detached: function() { | |
| 517 this.target.removeEventListener('mousedown', this._boundMousedownAction)
; | |
| 518 this.target.removeEventListener('mouseup', this._boundMouseupAction); | |
| 519 }, | |
| 520 | |
| 521 /* TODO(cdata): Replace the above attached / detached listeners when | |
| 522 PolymerGestures equivalent lands in 0.8. | |
| 523 listeners: { | |
| 524 mousedown: 'mousedownAction', | |
| 525 mouseup: 'mouseupAction' | |
| 526 }, | |
| 527 */ | |
| 528 | |
| 529 get shouldKeepAnimating () { | 588 get shouldKeepAnimating () { |
| 530 for (var index = 0; index < this.ripples.length; ++index) { | 589 for (var index = 0; index < this.ripples.length; ++index) { |
| 531 if (!this.ripples[index].isAnimationComplete) { | 590 if (!this.ripples[index].isAnimationComplete) { |
| 532 return true; | 591 return true; |
| 533 } | 592 } |
| 534 } | 593 } |
| 535 | 594 |
| 536 return false; | 595 return false; |
| 537 }, | 596 }, |
| 538 | 597 |
| 539 simulatedRipple: function() { | 598 simulatedRipple: function() { |
| 540 this.mousedownAction(null); | 599 this.downAction(null); |
| 541 | 600 |
| 542 // Please see polymer/polymer#1305 | 601 // Please see polymer/polymer#1305 |
| 543 this.async(function() { | 602 this.async(function() { |
| 544 this.mouseupAction(); | 603 this.upAction(); |
| 545 }, 1); | 604 }, 1); |
| 546 }, | 605 }, |
| 547 | 606 |
| 548 mousedownAction: function(event) { | 607 downAction: function(event) { |
| 608 if (this.holdDown && this.ripples.length > 0) { |
| 609 return; |
| 610 } |
| 611 |
| 549 var ripple = this.addRipple(); | 612 var ripple = this.addRipple(); |
| 550 | 613 |
| 551 ripple.mousedownAction(event); | 614 ripple.downAction(event); |
| 552 | 615 |
| 553 if (!this._animating) { | 616 if (!this._animating) { |
| 554 this.animate(); | 617 this.animate(); |
| 555 } | 618 } |
| 556 }, | 619 }, |
| 557 | 620 |
| 558 mouseupAction: function(event) { | 621 upAction: function(event) { |
| 622 if (this.holdDown) { |
| 623 return; |
| 624 } |
| 625 |
| 559 this.ripples.forEach(function(ripple) { | 626 this.ripples.forEach(function(ripple) { |
| 560 ripple.mouseupAction(event); | 627 ripple.upAction(event); |
| 561 }); | 628 }); |
| 562 | 629 |
| 563 this.animate(); | 630 this.animate(); |
| 564 }, | 631 }, |
| 565 | 632 |
| 566 onAnimationComplete: function() { | 633 onAnimationComplete: function() { |
| 567 this._animating = false; | 634 this._animating = false; |
| 568 this.$.background.style.backgroundColor = null; | 635 this.$.background.style.backgroundColor = null; |
| 569 this.fire('transitionend'); | 636 this.fire('transitionend'); |
| 570 }, | 637 }, |
| 571 | 638 |
| 572 addRipple: function() { | 639 addRipple: function() { |
| 573 var ripple = new Ripple(this); | 640 var ripple = new Ripple(this); |
| 574 | 641 |
| 575 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); | 642 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); |
| 576 this.$.background.style.backgroundColor = ripple.color; | 643 this.$.background.style.backgroundColor = ripple.color; |
| 577 this.ripples.push(ripple); | 644 this.ripples.push(ripple); |
| 578 | 645 |
| 646 this._setAnimating(true); |
| 647 |
| 579 return ripple; | 648 return ripple; |
| 580 }, | 649 }, |
| 581 | 650 |
| 582 removeRipple: function(ripple) { | 651 removeRipple: function(ripple) { |
| 583 var rippleIndex = this.ripples.indexOf(ripple); | 652 var rippleIndex = this.ripples.indexOf(ripple); |
| 584 | 653 |
| 585 if (rippleIndex < 0) { | 654 if (rippleIndex < 0) { |
| 586 return; | 655 return; |
| 587 } | 656 } |
| 588 | 657 |
| 589 this.ripples.splice(rippleIndex, 1); | 658 this.ripples.splice(rippleIndex, 1); |
| 590 | 659 |
| 591 ripple.remove(); | 660 ripple.remove(); |
| 661 |
| 662 if (!this.ripples.length) { |
| 663 this._setAnimating(false); |
| 664 } |
| 592 }, | 665 }, |
| 593 | 666 |
| 594 animate: function() { | 667 animate: function() { |
| 595 var index; | 668 var index; |
| 596 var ripple; | 669 var ripple; |
| 597 | 670 |
| 598 this._animating = true; | 671 this._animating = true; |
| 599 | 672 |
| 600 for (index = 0; index < this.ripples.length; ++index) { | 673 for (index = 0; index < this.ripples.length; ++index) { |
| 601 ripple = this.ripples[index]; | 674 ripple = this.ripples[index]; |
| 602 | 675 |
| 603 ripple.draw(); | 676 ripple.draw(); |
| 604 | 677 |
| 605 this.$.background.style.opacity = ripple.outerOpacity; | 678 this.$.background.style.opacity = ripple.outerOpacity; |
| 606 | 679 |
| 607 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { | 680 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { |
| 608 this.removeRipple(ripple); | 681 this.removeRipple(ripple); |
| 609 } | 682 } |
| 610 } | 683 } |
| 611 | 684 |
| 612 if (this.shouldKeepAnimating) { | 685 if (!this.shouldKeepAnimating && this.ripples.length === 0) { |
| 686 this.onAnimationComplete(); |
| 687 } else { |
| 613 window.requestAnimationFrame(this._boundAnimate); | 688 window.requestAnimationFrame(this._boundAnimate); |
| 614 } else if (this.ripples.length === 0) { | 689 } |
| 615 this.onAnimationComplete(); | 690 }, |
| 691 |
| 692 _onEnterKeydown: function() { |
| 693 this.downAction(); |
| 694 this.async(this.upAction, 1); |
| 695 }, |
| 696 |
| 697 _onSpaceKeydown: function() { |
| 698 this.downAction(); |
| 699 }, |
| 700 |
| 701 _onSpaceKeyup: function() { |
| 702 this.upAction(); |
| 703 }, |
| 704 |
| 705 _holdDownChanged: function(holdDown) { |
| 706 if (holdDown) { |
| 707 this.downAction(); |
| 708 } else { |
| 709 this.upAction(); |
| 616 } | 710 } |
| 617 } | 711 } |
| 618 }); | 712 }); |
| 619 })(); | 713 })(); |
| 620 </script> | 714 </script> |
| OLD | NEW |