Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / third_party / mdl / repo / src / ripple / ripple.js
1 /**
2  * @license
3  * Copyright 2015 Google Inc. All Rights Reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 (function() {
19   'use strict';
20
21   /**
22    * Class constructor for Ripple MDL component.
23    * Implements MDL component design pattern defined at:
24    * https://github.com/jasonmayes/mdl-component-design-pattern
25    *
26    * @constructor
27    * @param {HTMLElement} element The element that will be upgraded.
28    */
29   var MaterialRipple = function MaterialRipple(element) {
30     this.element_ = element;
31
32     // Initialize instance.
33     this.init();
34   };
35   window['MaterialRipple'] = MaterialRipple;
36
37   /**
38    * Store constants in one place so they can be updated easily.
39    *
40    * @enum {string | number}
41    * @private
42    */
43   MaterialRipple.prototype.Constant_ = {
44     INITIAL_SCALE: 'scale(0.0001, 0.0001)',
45     INITIAL_SIZE: '1px',
46     INITIAL_OPACITY: '0.4',
47     FINAL_OPACITY: '0',
48     FINAL_SCALE: ''
49   };
50
51   /**
52    * Store strings for class names defined by this component that are used in
53    * JavaScript. This allows us to simply change it in one place should we
54    * decide to modify at a later date.
55    *
56    * @enum {string}
57    * @private
58    */
59   MaterialRipple.prototype.CssClasses_ = {
60     RIPPLE_CENTER: 'mdl-ripple--center',
61     RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
62     RIPPLE: 'mdl-ripple',
63     IS_ANIMATING: 'is-animating',
64     IS_VISIBLE: 'is-visible'
65   };
66
67   /**
68    * Handle mouse / finger down on element.
69    *
70    * @param {Event} event The event that fired.
71    * @private
72    */
73   MaterialRipple.prototype.downHandler_ = function(event) {
74     if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {
75       var rect = this.element_.getBoundingClientRect();
76       this.boundHeight = rect.height;
77       this.boundWidth = rect.width;
78       this.rippleSize_ = Math.sqrt(rect.width * rect.width +
79           rect.height * rect.height) * 2 + 2;
80       this.rippleElement_.style.width = this.rippleSize_ + 'px';
81       this.rippleElement_.style.height = this.rippleSize_ + 'px';
82     }
83
84     this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE);
85
86     if (event.type === 'mousedown' && this.ignoringMouseDown_) {
87       this.ignoringMouseDown_ = false;
88     } else {
89       if (event.type === 'touchstart') {
90         this.ignoringMouseDown_ = true;
91       }
92       var frameCount = this.getFrameCount();
93       if (frameCount > 0) {
94         return;
95       }
96       this.setFrameCount(1);
97       var bound = event.currentTarget.getBoundingClientRect();
98       var x;
99       var y;
100       // Check if we are handling a keyboard click.
101       if (event.clientX === 0 && event.clientY === 0) {
102         x = Math.round(bound.width / 2);
103         y = Math.round(bound.height / 2);
104       } else {
105         var clientX = event.clientX !== undefined ? event.clientX : event.touches[0].clientX;
106         var clientY = event.clientY !== undefined ? event.clientY : event.touches[0].clientY;
107         x = Math.round(clientX - bound.left);
108         y = Math.round(clientY - bound.top);
109       }
110       this.setRippleXY(x, y);
111       this.setRippleStyles(true);
112       window.requestAnimationFrame(this.animFrameHandler.bind(this));
113     }
114   };
115
116   /**
117    * Handle mouse / finger up on element.
118    *
119    * @param {Event} event The event that fired.
120    * @private
121    */
122   MaterialRipple.prototype.upHandler_ = function(event) {
123     // Don't fire for the artificial "mouseup" generated by a double-click.
124     if (event && event.detail !== 2) {
125       // Allow a repaint to occur before removing this class, so the animation
126       // shows for tap events, which seem to trigger a mouseup too soon after
127       // mousedown.
128       window.setTimeout(function() {
129         this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE);
130       }.bind(this), 0);
131     }
132   };
133
134   /**
135    * Initialize element.
136    */
137   MaterialRipple.prototype.init = function() {
138     if (this.element_) {
139       var recentering =
140           this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER);
141       if (!this.element_.classList.contains(
142           this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) {
143         this.rippleElement_ = this.element_.querySelector('.' +
144             this.CssClasses_.RIPPLE);
145         this.frameCount_ = 0;
146         this.rippleSize_ = 0;
147         this.x_ = 0;
148         this.y_ = 0;
149
150         // Touch start produces a compat mouse down event, which would cause a
151         // second ripples. To avoid that, we use this property to ignore the first
152         // mouse down after a touch start.
153         this.ignoringMouseDown_ = false;
154
155         this.boundDownHandler = this.downHandler_.bind(this);
156         this.element_.addEventListener('mousedown',
157           this.boundDownHandler);
158         this.element_.addEventListener('touchstart',
159             this.boundDownHandler);
160
161         this.boundUpHandler = this.upHandler_.bind(this);
162         this.element_.addEventListener('mouseup', this.boundUpHandler);
163         this.element_.addEventListener('mouseleave', this.boundUpHandler);
164         this.element_.addEventListener('touchend', this.boundUpHandler);
165         this.element_.addEventListener('blur', this.boundUpHandler);
166
167         /**
168          * Getter for frameCount_.
169          * @return {number} the frame count.
170          */
171         this.getFrameCount = function() {
172           return this.frameCount_;
173         };
174
175         /**
176          * Setter for frameCount_.
177          * @param {number} fC the frame count.
178          */
179         this.setFrameCount = function(fC) {
180           this.frameCount_ = fC;
181         };
182
183         /**
184          * Getter for rippleElement_.
185          * @return {Element} the ripple element.
186          */
187         this.getRippleElement = function() {
188           return this.rippleElement_;
189         };
190
191         /**
192          * Sets the ripple X and Y coordinates.
193          * @param  {number} newX the new X coordinate
194          * @param  {number} newY the new Y coordinate
195          */
196         this.setRippleXY = function(newX, newY) {
197           this.x_ = newX;
198           this.y_ = newY;
199         };
200
201         /**
202          * Sets the ripple styles.
203          * @param  {boolean} start whether or not this is the start frame.
204          */
205         this.setRippleStyles = function(start) {
206           if (this.rippleElement_ !== null) {
207             var transformString;
208             var scale;
209             var size;
210             var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)';
211
212             if (start) {
213               scale = this.Constant_.INITIAL_SCALE;
214               size = this.Constant_.INITIAL_SIZE;
215             } else {
216               scale = this.Constant_.FINAL_SCALE;
217               size = this.rippleSize_ + 'px';
218               if (recentering) {
219                 offset = 'translate(' + this.boundWidth / 2 + 'px, ' +
220                   this.boundHeight / 2 + 'px)';
221               }
222             }
223
224             transformString = 'translate(-50%, -50%) ' + offset + scale;
225
226             this.rippleElement_.style.webkitTransform = transformString;
227             this.rippleElement_.style.msTransform = transformString;
228             this.rippleElement_.style.transform = transformString;
229
230             if (start) {
231               this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING);
232             } else {
233               this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING);
234             }
235           }
236         };
237
238         /**
239          * Handles an animation frame.
240          */
241         this.animFrameHandler = function() {
242           if (this.frameCount_-- > 0) {
243             window.requestAnimationFrame(this.animFrameHandler.bind(this));
244           } else {
245             this.setRippleStyles(false);
246           }
247         };
248       }
249     }
250   };
251
252   // The component registers itself. It can assume componentHandler is available
253   // in the global scope.
254   componentHandler.register({
255     constructor: MaterialRipple,
256     classAsString: 'MaterialRipple',
257     cssClass: 'mdl-js-ripple-effect',
258     widget: false
259   });
260 })();