allow string based values for comboboxarray
[roojs1] / Roo / QuickTips.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11 /**
12  * @class Roo.QuickTips
13  * Provides attractive and customizable tooltips for any element.
14  * @singleton
15  */
16 Roo.QuickTips = function(){
17     var el, tipBody, tipBodyText, tipTitle, tm, cfg, close, tagEls = {}, esc, removeCls = null, bdLeft, bdRight;
18     var ce, bd, xy, dd;
19     var visible = false, disabled = true, inited = false;
20     var showProc = 1, hideProc = 1, dismissProc = 1, locks = [];
21     
22     var onOver = function(e){
23         if(disabled){
24             return;
25         }
26         var t = e.getTarget();
27         if(!t || t.nodeType !== 1 || t == document || t == document.body){
28             return;
29         }
30         if(ce && t == ce.el){
31             clearTimeout(hideProc);
32             return;
33         }
34         if(t && tagEls[t.id]){
35             tagEls[t.id].el = t;
36             showProc = show.defer(tm.showDelay, tm, [tagEls[t.id]]);
37             return;
38         }
39         var ttp, et = Roo.fly(t);
40         var ns = cfg.namespace;
41         if(tm.interceptTitles && t.title){
42             ttp = t.title;
43             t.qtip = ttp;
44             t.removeAttribute("title");
45             e.preventDefault();
46         }else{
47             ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute) || et.getAttributeNS(cfg.alt_namespace, cfg.attribute) ;
48         }
49         if(ttp){
50             showProc = show.defer(tm.showDelay, tm, [{
51                 el: t, 
52                 text: ttp.replace(/\\n/g,'<br/>'),
53                 width: et.getAttributeNS(ns, cfg.width),
54                 autoHide: et.getAttributeNS(ns, cfg.hide) != "user",
55                 title: et.getAttributeNS(ns, cfg.title),
56                     cls: et.getAttributeNS(ns, cfg.cls)
57             }]);
58         }
59     };
60     
61     var onOut = function(e){
62         clearTimeout(showProc);
63         var t = e.getTarget();
64         if(t && ce && ce.el == t && (tm.autoHide && ce.autoHide !== false)){
65             hideProc = setTimeout(hide, tm.hideDelay);
66         }
67     };
68     
69     var onMove = function(e){
70         if(disabled){
71             return;
72         }
73         xy = e.getXY();
74         xy[1] += 18;
75         if(tm.trackMouse && ce){
76             el.setXY(xy);
77         }
78     };
79     
80     var onDown = function(e){
81         clearTimeout(showProc);
82         clearTimeout(hideProc);
83         if(!e.within(el)){
84             if(tm.hideOnClick){
85                 hide();
86                 tm.disable();
87                 tm.enable.defer(100, tm);
88             }
89         }
90     };
91     
92     var getPad = function(){
93         return 2;//bdLeft.getPadding('l')+bdRight.getPadding('r');
94     };
95
96     var show = function(o){
97         if(disabled){
98             return;
99         }
100         clearTimeout(dismissProc);
101         ce = o;
102         if(removeCls){ // in case manually hidden
103             el.removeClass(removeCls);
104             removeCls = null;
105         }
106         if(ce.cls){
107             el.addClass(ce.cls);
108             removeCls = ce.cls;
109         }
110         if(ce.title){
111             tipTitle.update(ce.title);
112             tipTitle.show();
113         }else{
114             tipTitle.update('');
115             tipTitle.hide();
116         }
117         el.dom.style.width  = tm.maxWidth+'px';
118         //tipBody.dom.style.width = '';
119         tipBodyText.update(o.text);
120         var p = getPad(), w = ce.width;
121         if(!w){
122             var td = tipBodyText.dom;
123             var aw = Math.max(td.offsetWidth, td.clientWidth, td.scrollWidth);
124             if(aw > tm.maxWidth){
125                 w = tm.maxWidth;
126             }else if(aw < tm.minWidth){
127                 w = tm.minWidth;
128             }else{
129                 w = aw;
130             }
131         }
132         //tipBody.setWidth(w);
133         el.setWidth(parseInt(w, 10) + p);
134         if(ce.autoHide === false){
135             close.setDisplayed(true);
136             if(dd){
137                 dd.unlock();
138             }
139         }else{
140             close.setDisplayed(false);
141             if(dd){
142                 dd.lock();
143             }
144         }
145         if(xy){
146             el.avoidY = xy[1]-18;
147             el.setXY(xy);
148         }
149         if(tm.animate){
150             el.setOpacity(.1);
151             el.setStyle("visibility", "visible");
152             el.fadeIn({callback: afterShow});
153         }else{
154             afterShow();
155         }
156     };
157     
158     var afterShow = function(){
159         if(ce){
160             el.show();
161             esc.enable();
162             if(tm.autoDismiss && ce.autoHide !== false){
163                 dismissProc = setTimeout(hide, tm.autoDismissDelay);
164             }
165         }
166     };
167     
168     var hide = function(noanim){
169         clearTimeout(dismissProc);
170         clearTimeout(hideProc);
171         ce = null;
172         if(el.isVisible()){
173             esc.disable();
174             if(noanim !== true && tm.animate){
175                 el.fadeOut({callback: afterHide});
176             }else{
177                 afterHide();
178             } 
179         }
180     };
181     
182     var afterHide = function(){
183         el.hide();
184         if(removeCls){
185             el.removeClass(removeCls);
186             removeCls = null;
187         }
188     };
189     
190     return {
191         /**
192         * @cfg {Number} minWidth
193         * The minimum width of the quick tip (defaults to 40)
194         */
195        minWidth : 40,
196         /**
197         * @cfg {Number} maxWidth
198         * The maximum width of the quick tip (defaults to 300)
199         */
200        maxWidth : 300,
201         /**
202         * @cfg {Boolean} interceptTitles
203         * True to automatically use the element's DOM title value if available (defaults to false)
204         */
205        interceptTitles : false,
206         /**
207         * @cfg {Boolean} trackMouse
208         * True to have the quick tip follow the mouse as it moves over the target element (defaults to false)
209         */
210        trackMouse : false,
211         /**
212         * @cfg {Boolean} hideOnClick
213         * True to hide the quick tip if the user clicks anywhere in the document (defaults to true)
214         */
215        hideOnClick : true,
216         /**
217         * @cfg {Number} showDelay
218         * Delay in milliseconds before the quick tip displays after the mouse enters the target element (defaults to 500)
219         */
220        showDelay : 500,
221         /**
222         * @cfg {Number} hideDelay
223         * Delay in milliseconds before the quick tip hides when autoHide = true (defaults to 200)
224         */
225        hideDelay : 200,
226         /**
227         * @cfg {Boolean} autoHide
228         * True to automatically hide the quick tip after the mouse exits the target element (defaults to true).
229         * Used in conjunction with hideDelay.
230         */
231        autoHide : true,
232         /**
233         * @cfg {Boolean}
234         * True to automatically hide the quick tip after a set period of time, regardless of the user's actions
235         * (defaults to true).  Used in conjunction with autoDismissDelay.
236         */
237        autoDismiss : true,
238         /**
239         * @cfg {Number}
240         * Delay in milliseconds before the quick tip hides when autoDismiss = true (defaults to 5000)
241         */
242        autoDismissDelay : 5000,
243        /**
244         * @cfg {Boolean} animate
245         * True to turn on fade animation. Defaults to false (ClearType/scrollbar flicker issues in IE7).
246         */
247        animate : false,
248
249        /**
250         * @cfg {String} title
251         * Title text to display (defaults to '').  This can be any valid HTML markup.
252         */
253         title: '',
254        /**
255         * @cfg {String} text
256         * Body text to display (defaults to '').  This can be any valid HTML markup.
257         */
258         text : '',
259        /**
260         * @cfg {String} cls
261         * A CSS class to apply to the base quick tip element (defaults to '').
262         */
263         cls : '',
264        /**
265         * @cfg {Number} width
266         * Width in pixels of the quick tip (defaults to auto).  Width will be ignored if it exceeds the bounds of
267         * minWidth or maxWidth.
268         */
269         width : null,
270
271     /**
272      * Initialize and enable QuickTips for first use.  This should be called once before the first attempt to access
273      * or display QuickTips in a page.
274      */
275        init : function(){
276           tm = Roo.QuickTips;
277           cfg = tm.tagConfig;
278           if(!inited){
279               if(!Roo.isReady){ // allow calling of init() before onReady
280                   Roo.onReady(Roo.QuickTips.init, Roo.QuickTips);
281                   return;
282               }
283               el = new Roo.Layer({cls:"x-tip", shadow:"drop", shim: true, constrain:true, shadowOffset:4});
284               el.fxDefaults = {stopFx: true};
285               // maximum custom styling
286               //el.update('<div class="x-tip-top-left"><div class="x-tip-top-right"><div class="x-tip-top"></div></div></div><div class="x-tip-bd-left"><div class="x-tip-bd-right"><div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div></div></div><div class="x-tip-ft-left"><div class="x-tip-ft-right"><div class="x-tip-ft"></div></div></div>');
287               el.update('<div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div>');              
288               tipTitle = el.child('h3');
289               tipTitle.enableDisplayMode("block");
290               tipBody = el.child('div.x-tip-bd');
291               tipBodyText = el.child('div.x-tip-bd-inner');
292               //bdLeft = el.child('div.x-tip-bd-left');
293               //bdRight = el.child('div.x-tip-bd-right');
294               close = el.child('div.x-tip-close');
295               close.enableDisplayMode("block");
296               close.on("click", hide);
297               var d = Roo.get(document);
298               d.on("mousedown", onDown);
299               d.on("mouseover", onOver);
300               d.on("mouseout", onOut);
301               d.on("mousemove", onMove);
302               esc = d.addKeyListener(27, hide);
303               esc.disable();
304               if(Roo.dd.DD){
305                   dd = el.initDD("default", null, {
306                       onDrag : function(){
307                           el.sync();  
308                       }
309                   });
310                   dd.setHandleElId(tipTitle.id);
311                   dd.lock();
312               }
313               inited = true;
314           }
315           this.enable(); 
316        },
317
318     /**
319      * Configures a new quick tip instance and assigns it to a target element.  The following config options
320      * are supported:
321      * <pre>
322 Property    Type                   Description
323 ----------  ---------------------  ------------------------------------------------------------------------
324 target      Element/String/Array   An Element, id or array of ids that this quick tip should be tied to
325      * </ul>
326      * @param {Object} config The config object
327      */
328        register : function(config){
329            var cs = config instanceof Array ? config : arguments;
330            for(var i = 0, len = cs.length; i < len; i++) {
331                var c = cs[i];
332                var target = c.target;
333                if(target){
334                    if(target instanceof Array){
335                        for(var j = 0, jlen = target.length; j < jlen; j++){
336                            tagEls[target[j]] = c;
337                        }
338                    }else{
339                        tagEls[typeof target == 'string' ? target : Roo.id(target)] = c;
340                    }
341                }
342            }
343        },
344
345     /**
346      * Removes this quick tip from its element and destroys it.
347      * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
348      */
349        unregister : function(el){
350            delete tagEls[Roo.id(el)];
351        },
352
353     /**
354      * Enable this quick tip.
355      */
356        enable : function(){
357            if(inited && disabled){
358                locks.pop();
359                if(locks.length < 1){
360                    disabled = false;
361                }
362            }
363        },
364
365     /**
366      * Disable this quick tip.
367      */
368        disable : function(){
369           disabled = true;
370           clearTimeout(showProc);
371           clearTimeout(hideProc);
372           clearTimeout(dismissProc);
373           if(ce){
374               hide(true);
375           }
376           locks.push(1);
377        },
378
379     /**
380      * Returns true if the quick tip is enabled, else false.
381      */
382        isEnabled : function(){
383             return !disabled;
384        },
385
386         // private
387        tagConfig : {
388            namespace : "roo", // was ext?? this may break..
389            alt_namespace : "ext",
390            attribute : "qtip",
391            width : "width",
392            target : "target",
393            title : "qtitle",
394            hide : "hide",
395            cls : "qclass"
396        }
397    };
398 }();
399
400 // backwards compat
401 Roo.QuickTips.tips = Roo.QuickTips.register;