X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/tip/QuickTip.js?ds=sidebyside diff --git a/src/tip/QuickTip.js b/src/tip/QuickTip.js new file mode 100644 index 00000000..b6a2f58f --- /dev/null +++ b/src/tip/QuickTip.js @@ -0,0 +1,265 @@ +/** + * @class Ext.tip.QuickTip + * @extends Ext.tip.ToolTip + * A specialized tooltip class for tooltips that can be specified in markup and automatically managed by the global + * {@link Ext.tip.QuickTipManager} instance. See the QuickTipManager class header for additional usage details and examples. + * @constructor + * Create a new Tip + * @param {Object} config The configuration options + * @xtype quicktip + */ +Ext.define('Ext.tip.QuickTip', { + extend: 'Ext.tip.ToolTip', + alternateClassName: 'Ext.QuickTip', + /** + * @cfg {Mixed} target The target HTMLElement, Ext.core.Element or id to associate with this Quicktip (defaults to the document). + */ + /** + * @cfg {Boolean} interceptTitles True to automatically use the element's DOM title value if available (defaults to false). + */ + interceptTitles : false, + + // Force creation of header Component + title: ' ', + + // private + tagConfig : { + namespace : "data-", + attribute : "qtip", + width : "qwidth", + target : "target", + title : "qtitle", + hide : "hide", + cls : "qclass", + align : "qalign", + anchor : "anchor" + }, + + // private + initComponent : function(){ + var me = this; + + me.target = me.target || Ext.getDoc(); + me.targets = me.targets || {}; + me.callParent(); + }, + + /** + * Configures a new quick tip instance and assigns it to a target element. The following config values are + * supported (for example usage, see the {@link Ext.tip.QuickTipManager} class header): + *
+ * @param {Object} config The config object + */ + register : function(config){ + var configs = Ext.isArray(config) ? config : arguments, + i = 0, + len = configs.length, + target, j, targetLen; + + for (; i < len; i++) { + config = configs[i]; + target = config.target; + if (target) { + if (Ext.isArray(target)) { + for (j = 0, targetLen = target.length; j < targetLen; j++) { + this.targets[Ext.id(target[j])] = config; + } + } else{ + this.targets[Ext.id(target)] = config; + } + } + } + }, + + /** + * Removes this quick tip from its element and destroys it. + * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed. + */ + unregister : function(el){ + delete this.targets[Ext.id(el)]; + }, + + /** + * Hides a visible tip or cancels an impending show for a particular element. + * @param {String/HTMLElement/Element} el The element that is the target of the tip. + */ + cancelShow: function(el){ + var me = this, + activeTarget = me.activeTarget; + + el = Ext.get(el).dom; + if (me.isVisible()) { + if (activeTarget && activeTarget.el == el) { + me.hide(); + } + } else if (activeTarget && activeTarget.el == el) { + me.clearTimer('show'); + } + }, + + getTipCfg: function(e) { + var t = e.getTarget(), + ttp, + cfg; + + if(this.interceptTitles && t.title && Ext.isString(t.title)){ + ttp = t.title; + t.qtip = ttp; + t.removeAttribute("title"); + e.preventDefault(); + } + else { + cfg = this.tagConfig; + t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']'); + if (t) { + ttp = t.getAttribute(cfg.namespace + cfg.attribute); + } + } + return ttp; + }, + + // private + onTargetOver : function(e){ + var me = this, + target = e.getTarget(), + elTarget, + cfg, + ns, + ttp, + autoHide; + + if (me.disabled) { + return; + } + + // TODO - this causes "e" to be recycled in IE6/7 (EXTJSIV-1608) so ToolTip#setTarget + // was changed to include freezeEvent. The issue seems to be a nested 'resize' event + // that smashed Ext.EventObject. + me.targetXY = e.getXY(); + + if(!target || target.nodeType !== 1 || target == document || target == document.body){ + return; + } + + if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) { + me.clearTimer('hide'); + me.show(); + return; + } + + if (target) { + Ext.Object.each(me.targets, function(key, value) { + var targetEl = Ext.fly(value.target); + if (targetEl && (targetEl.dom === target || targetEl.contains(target))) { + elTarget = targetEl.dom; + return false; + } + }); + if (elTarget) { + me.activeTarget = me.targets[elTarget.id]; + me.activeTarget.el = target; + me.anchor = me.activeTarget.anchor; + if (me.anchor) { + me.anchorTarget = target; + } + me.delayShow(); + return; + } + } + + elTarget = Ext.get(target); + cfg = me.tagConfig; + ns = cfg.namespace; + ttp = me.getTipCfg(e); + + if (ttp) { + autoHide = elTarget.getAttribute(ns + cfg.hide); + + me.activeTarget = { + el: target, + text: ttp, + width: +elTarget.getAttribute(ns + cfg.width) || null, + autoHide: autoHide != "user" && autoHide !== 'false', + title: elTarget.getAttribute(ns + cfg.title), + cls: elTarget.getAttribute(ns + cfg.cls), + align: elTarget.getAttribute(ns + cfg.align) + + }; + me.anchor = elTarget.getAttribute(ns + cfg.anchor); + if (me.anchor) { + me.anchorTarget = target; + } + me.delayShow(); + } + }, + + // private + onTargetOut : function(e){ + var me = this; + + // If moving within the current target, and it does not have a new tip, ignore the mouseout + if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) { + return; + } + + me.clearTimer('show'); + if (me.autoHide !== false) { + me.delayHide(); + } + }, + + // inherit docs + showAt : function(xy){ + var me = this, + target = me.activeTarget; + + if (target) { + if (!me.rendered) { + me.render(Ext.getBody()); + me.activeTarget = target; + } + if (target.title) { + me.setTitle(target.title || ''); + me.header.show(); + } else { + me.header.hide(); + } + me.body.update(target.text); + me.autoHide = target.autoHide; + me.dismissDelay = target.dismissDelay || me.dismissDelay; + if (me.lastCls) { + me.el.removeCls(me.lastCls); + delete me.lastCls; + } + if (target.cls) { + me.el.addCls(target.cls); + me.lastCls = target.cls; + } + + me.setWidth(target.width); + + if (me.anchor) { + me.constrainPosition = false; + } else if (target.align) { // TODO: this doesn't seem to work consistently + xy = me.el.getAlignToXY(target.el, target.align); + me.constrainPosition = false; + }else{ + me.constrainPosition = true; + } + } + me.callParent([xy]); + }, + + // inherit docs + hide: function(){ + delete this.activeTarget; + this.callParent(); + } +});