PageRenderTime 28ms CodeModel.GetById 15ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 0ms

/ext-4.0.7/src/tip/QuickTip.js

https://bitbucket.org/srogerf/javascript
JavaScript | 294 lines | 196 code | 31 blank | 67 comment | 57 complexity | f323b6a1a13c436d21b7f0c221ed9834 MD5 | raw file
  1/*
  2
  3This file is part of Ext JS 4
  4
  5Copyright (c) 2011 Sencha Inc
  6
  7Contact:  http://www.sencha.com/contact
  8
  9GNU General Public License Usage
 10This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
 11
 12If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
 13
 14*/
 15/**
 16 * @class Ext.tip.QuickTip
 17 * @extends Ext.tip.ToolTip
 18 * A specialized tooltip class for tooltips that can be specified in markup and automatically managed by the global
 19 * {@link Ext.tip.QuickTipManager} instance.  See the QuickTipManager documentation for additional usage details and examples.
 20 * @xtype quicktip
 21 */
 22Ext.define('Ext.tip.QuickTip', {
 23    extend: 'Ext.tip.ToolTip',
 24    alternateClassName: 'Ext.QuickTip',
 25    /**
 26     * @cfg {String/HTMLElement/Ext.Element} target The target HTMLElement, Ext.Element or id to associate with this Quicktip (defaults to the document).
 27     */
 28    /**
 29     * @cfg {Boolean} interceptTitles True to automatically use the element's DOM title value if available.
 30     */
 31    interceptTitles : false,
 32
 33    // Force creation of header Component
 34    title: ' ',
 35
 36    // private
 37    tagConfig : {
 38        namespace : "data-",
 39        attribute : "qtip",
 40        width : "qwidth",
 41        target : "target",
 42        title : "qtitle",
 43        hide : "hide",
 44        cls : "qclass",
 45        align : "qalign",
 46        anchor : "anchor"
 47    },
 48
 49    // private
 50    initComponent : function(){
 51        var me = this;
 52
 53        me.target = me.target || Ext.getDoc();
 54        me.targets = me.targets || {};
 55        me.callParent();
 56    },
 57
 58    /**
 59     * Configures a new quick tip instance and assigns it to a target element.  The following config values are
 60     * supported (for example usage, see the {@link Ext.tip.QuickTipManager} class header):
 61     * <div class="mdetail-params"><ul>
 62     * <li>autoHide</li>
 63     * <li>cls</li>
 64     * <li>dismissDelay (overrides the singleton value)</li>
 65     * <li>target (required)</li>
 66     * <li>text (required)</li>
 67     * <li>title</li>
 68     * <li>width</li></ul></div>
 69     * @param {Object} config The config object
 70     */
 71    register : function(config){
 72        var configs = Ext.isArray(config) ? config : arguments,
 73            i = 0,
 74            len = configs.length,
 75            target, j, targetLen;
 76
 77        for (; i < len; i++) {
 78            config = configs[i];
 79            target = config.target;
 80            if (target) {
 81                if (Ext.isArray(target)) {
 82                    for (j = 0, targetLen = target.length; j < targetLen; j++) {
 83                        this.targets[Ext.id(target[j])] = config;
 84                    }
 85                } else{
 86                    this.targets[Ext.id(target)] = config;
 87                }
 88            }
 89        }
 90    },
 91
 92    /**
 93     * Removes this quick tip from its element and destroys it.
 94     * @param {String/HTMLElement/Ext.Element} el The element from which the quick tip is to be removed or ID of the element.
 95     */
 96    unregister : function(el){
 97        delete this.targets[Ext.id(el)];
 98    },
 99
100    /**
101     * Hides a visible tip or cancels an impending show for a particular element.
102     * @param {String/HTMLElement/Ext.Element} el The element that is the target of the tip or ID of the element.
103     */
104    cancelShow: function(el){
105        var me = this,
106            activeTarget = me.activeTarget;
107
108        el = Ext.get(el).dom;
109        if (me.isVisible()) {
110            if (activeTarget && activeTarget.el == el) {
111                me.hide();
112            }
113        } else if (activeTarget && activeTarget.el == el) {
114            me.clearTimer('show');
115        }
116    },
117
118    /**
119     * @private
120     * Reads the tip text from the closest node to the event target which contains the attribute we
121     * are configured to look for. Returns an object containing the text from the attribute, and the target element from
122     * which the text was read.
123     */
124    getTipCfg: function(e) {
125        var t = e.getTarget(),
126            titleText = t.title,
127            cfg;
128
129        if (this.interceptTitles && titleText && Ext.isString(titleText)) {
130            t.qtip = titleText;
131            t.removeAttribute("title");
132            e.preventDefault();
133            return {
134                text: titleText
135            };
136        }
137        else {
138            cfg = this.tagConfig;
139            t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
140            if (t) {
141                return {
142                    target: t,
143                    text: t.getAttribute(cfg.namespace + cfg.attribute)
144                };
145            }
146        }
147    },
148
149    // private
150    onTargetOver : function(e){
151        var me = this,
152            target = e.getTarget(),
153            elTarget,
154            cfg,
155            ns,
156            tipConfig,
157            autoHide;
158
159        if (me.disabled) {
160            return;
161        }
162
163        // TODO - this causes "e" to be recycled in IE6/7 (EXTJSIV-1608) so ToolTip#setTarget
164        // was changed to include freezeEvent. The issue seems to be a nested 'resize' event
165        // that smashed Ext.EventObject.
166        me.targetXY = e.getXY();
167
168        if(!target || target.nodeType !== 1 || target == document || target == document.body){
169            return;
170        }
171
172        if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
173            me.clearTimer('hide');
174            me.show();
175            return;
176        }
177
178        if (target) {
179            Ext.Object.each(me.targets, function(key, value) {
180                var targetEl = Ext.fly(value.target);
181                if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
182                    elTarget = targetEl.dom;
183                    return false;
184                }
185            });
186            if (elTarget) {
187                me.activeTarget = me.targets[elTarget.id];
188                me.activeTarget.el = target;
189                me.anchor = me.activeTarget.anchor;
190                if (me.anchor) {
191                    me.anchorTarget = target;
192                }
193                me.delayShow();
194                return;
195            }
196        }
197
198        elTarget = Ext.get(target);
199        cfg = me.tagConfig;
200        ns = cfg.namespace;
201        tipConfig = me.getTipCfg(e);
202
203        if (tipConfig) {
204
205            // getTipCfg may look up the parentNode axis for a tip text attribute and will return the new target node.
206            // Change our target element to match that from which the tip text attribute was read.
207            if (tipConfig.target) {
208                target = tipConfig.target;
209                elTarget = Ext.get(target);
210            }
211            autoHide = elTarget.getAttribute(ns + cfg.hide);
212
213            me.activeTarget = {
214                el: target,
215                text: tipConfig.text,
216                width: +elTarget.getAttribute(ns + cfg.width) || null,
217                autoHide: autoHide != "user" && autoHide !== 'false',
218                title: elTarget.getAttribute(ns + cfg.title),
219                cls: elTarget.getAttribute(ns + cfg.cls),
220                align: elTarget.getAttribute(ns + cfg.align)
221
222            };
223            me.anchor = elTarget.getAttribute(ns + cfg.anchor);
224            if (me.anchor) {
225                me.anchorTarget = target;
226            }
227            me.delayShow();
228        }
229    },
230
231    // private
232    onTargetOut : function(e){
233        var me = this;
234
235        // If moving within the current target, and it does not have a new tip, ignore the mouseout
236        if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
237            return;
238        }
239
240        me.clearTimer('show');
241        if (me.autoHide !== false) {
242            me.delayHide();
243        }
244    },
245
246    // inherit docs
247    showAt : function(xy){
248        var me = this,
249            target = me.activeTarget;
250
251        if (target) {
252            if (!me.rendered) {
253                me.render(Ext.getBody());
254                me.activeTarget = target;
255            }
256            if (target.title) {
257                me.setTitle(target.title || '');
258                me.header.show();
259            } else {
260                me.header.hide();
261            }
262            me.body.update(target.text);
263            me.autoHide = target.autoHide;
264            me.dismissDelay = target.dismissDelay || me.dismissDelay;
265            if (me.lastCls) {
266                me.el.removeCls(me.lastCls);
267                delete me.lastCls;
268            }
269            if (target.cls) {
270                me.el.addCls(target.cls);
271                me.lastCls = target.cls;
272            }
273
274            me.setWidth(target.width);
275
276            if (me.anchor) {
277                me.constrainPosition = false;
278            } else if (target.align) { // TODO: this doesn't seem to work consistently
279                xy = me.el.getAlignToXY(target.el, target.align);
280                me.constrainPosition = false;
281            }else{
282                me.constrainPosition = true;
283            }
284        }
285        me.callParent([xy]);
286    },
287
288    // inherit docs
289    hide: function(){
290        delete this.activeTarget;
291        this.callParent();
292    }
293});
294