commit extjs-2.2.1
[extjs.git] / source / util / ClickRepeater.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 /**\r
10  @class Ext.util.ClickRepeater\r
11  @extends Ext.util.Observable\r
12 \r
13  A wrapper class which can be applied to any element. Fires a "click" event while the\r
14  mouse is pressed. The interval between firings may be specified in the config but\r
15  defaults to 20 milliseconds.\r
16 \r
17  Optionally, a CSS class may be applied to the element during the time it is pressed.\r
18 \r
19  @cfg {Mixed} el The element to act as a button.\r
20  @cfg {Number} delay The initial delay before the repeating event begins firing.\r
21  Similar to an autorepeat key delay.\r
22  @cfg {Number} interval The interval between firings of the "click" event. Default 20 ms.\r
23  @cfg {String} pressClass A CSS class name to be applied to the element while pressed.\r
24  @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.\r
25            "interval" and "delay" are ignored.\r
26  @cfg {Boolean} preventDefault True to prevent the default click event\r
27  @cfg {Boolean} stopDefault True to stop the default click event\r
28 \r
29  @history\r
30     2007-02-02 jvs Original code contributed by Nige "Animal" White\r
31     2007-02-02 jvs Renamed to ClickRepeater\r
32     2007-02-03 jvs Modifications for FF Mac and Safari\r
33 \r
34  @constructor\r
35  @param {Mixed} el The element to listen on\r
36  @param {Object} config\r
37  */\r
38 Ext.util.ClickRepeater = function(el, config)\r
39 {\r
40     this.el = Ext.get(el);\r
41     this.el.unselectable();\r
42 \r
43     Ext.apply(this, config);\r
44 \r
45     this.addEvents(\r
46     /**\r
47      * @event mousedown\r
48      * Fires when the mouse button is depressed.\r
49      * @param {Ext.util.ClickRepeater} this\r
50      */\r
51         "mousedown",\r
52     /**\r
53      * @event click\r
54      * Fires on a specified interval during the time the element is pressed.\r
55      * @param {Ext.util.ClickRepeater} this\r
56      */\r
57         "click",\r
58     /**\r
59      * @event mouseup\r
60      * Fires when the mouse key is released.\r
61      * @param {Ext.util.ClickRepeater} this\r
62      */\r
63         "mouseup"\r
64     );\r
65 \r
66     this.el.on("mousedown", this.handleMouseDown, this);\r
67     if(this.preventDefault || this.stopDefault){\r
68         this.el.on("click", function(e){\r
69             if(this.preventDefault){\r
70                 e.preventDefault();\r
71             }\r
72             if(this.stopDefault){\r
73                 e.stopEvent();\r
74             }\r
75         }, this);\r
76     }\r
77 \r
78     // allow inline handler\r
79     if(this.handler){\r
80         this.on("click", this.handler,  this.scope || this);\r
81     }\r
82 \r
83     Ext.util.ClickRepeater.superclass.constructor.call(this);\r
84 };\r
85 \r
86 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {\r
87     interval : 20,\r
88     delay: 250,\r
89     preventDefault : true,\r
90     stopDefault : false,\r
91     timer : 0,\r
92 \r
93     // private\r
94     destroy : function() {\r
95         Ext.destroy(this.el);\r
96         this.purgeListeners();\r
97     },\r
98     \r
99     // private\r
100     handleMouseDown : function(){\r
101         clearTimeout(this.timer);\r
102         this.el.blur();\r
103         if(this.pressClass){\r
104             this.el.addClass(this.pressClass);\r
105         }\r
106         this.mousedownTime = new Date();\r
107 \r
108         Ext.getDoc().on("mouseup", this.handleMouseUp, this);\r
109         this.el.on("mouseout", this.handleMouseOut, this);\r
110 \r
111         this.fireEvent("mousedown", this);\r
112         this.fireEvent("click", this);\r
113 \r
114 //      Do not honor delay or interval if acceleration wanted.\r
115         if (this.accelerate) {\r
116             this.delay = 400;\r
117             }\r
118         this.timer = this.click.defer(this.delay || this.interval, this);\r
119     },\r
120 \r
121     // private\r
122     click : function(){\r
123         this.fireEvent("click", this);\r
124         this.timer = this.click.defer(this.accelerate ?\r
125             this.easeOutExpo(this.mousedownTime.getElapsed(),\r
126                 400,\r
127                 -390,\r
128                 12000) :\r
129             this.interval, this);\r
130     },\r
131 \r
132     easeOutExpo : function (t, b, c, d) {\r
133         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;\r
134     },\r
135 \r
136     // private\r
137     handleMouseOut : function(){\r
138         clearTimeout(this.timer);\r
139         if(this.pressClass){\r
140             this.el.removeClass(this.pressClass);\r
141         }\r
142         this.el.on("mouseover", this.handleMouseReturn, this);\r
143     },\r
144 \r
145     // private\r
146     handleMouseReturn : function(){\r
147         this.el.un("mouseover", this.handleMouseReturn, this);\r
148         if(this.pressClass){\r
149             this.el.addClass(this.pressClass);\r
150         }\r
151         this.click();\r
152     },\r
153 \r
154     // private\r
155     handleMouseUp : function(){\r
156         clearTimeout(this.timer);\r
157         this.el.un("mouseover", this.handleMouseReturn, this);\r
158         this.el.un("mouseout", this.handleMouseOut, this);\r
159         Ext.getDoc().un("mouseup", this.handleMouseUp, this);\r
160         this.el.removeClass(this.pressClass);\r
161         this.fireEvent("mouseup", this);\r
162     }\r
163 });