PDA

View Full Version : Better tooltip positioning



Jangla
19 Mar 2013, 12:43 AM
So for as long as I can remember we've been using the following code to add tooltips to form fields when the user gives them focus:



Ext.define( 'Ext.ux.form.FieldTip', {
extend : Object,
alias : 'plugin.fieldtip',
init : function ( field ){
field.on( {
focus : function (){
if ( !this.tip ) {
var tipCfg = {
autoHide : false,
anchor : this.qanchor,
shadow : false,
anchorOffset : 8
};
if ( Ext.isString( this.qtip ) ) {
tipCfg.html = this.qtip;
} else {
tipCfg.html = this.qtip.text;
Ext.apply( tipCfg, this.qtip );
}
this.tip = new Ext.ToolTip( tipCfg );
this.tip.target = this.tip.anchorTarget = this.el;
}
if ( this.qtip.text ) {
this.tip.show();
}
},
blur : function (){
if ( this.tip ) {
this.tip.hide();
}
},
destroy : function (){
if ( this.tip ) {
this.tip.destroy();
delete this.tip;
}
}
} );
}
} );


It works reasonably well but has one major shortfall that I've been struggling to rectify - we can't position the tip at the mid point of a form field.

Attached is a screenshot showing why this can be a problem in some circumstances - we'd love to be able to dynamically ensure that the tip had it's anchor mark 50% of the way down the tip's side and the tip itself was either manually positioned on a case-by-base basis or programatically worked out how to position itself along the mid line of the control it was anchored to.

Bear in mind, we've converted this code from some pretty old v3 code so if there are better ways to achieve a better result with the positioning issues addressed too, I'm all ears :D

mitchellsimoens
21 Mar 2013, 6:22 AM
I usually use the showBy method on Ext.tip.ToolTip as you can pass a position string like 'c-c?' and it will figure out how to align it properly.

Jangla
21 Mar 2013, 6:47 AM
I've already tried swapping out the show call with:



this.tip.showBy(this.el.id, 'c-c')


And it just throws this:



Uncaught TypeError: Cannot call method 'getAlignToXY' of undefined

mitchellsimoens
21 Mar 2013, 6:52 AM
This this.el instead of this.el.id

Jangla
21 Mar 2013, 6:57 AM
Same result

mitchellsimoens
21 Mar 2013, 7:52 AM
Quick little test:


Ext.define('MyPlugin', {
extend : 'Ext.AbstractPlugin',
alias : 'plugin.myplugin',

requires : 'Ext.tip.ToolTip',

/**
* @private
* Holds the Ext.tip.ToolTip instance
*/
_tip : null,
/**
* @cfg {String} title The title to show in the tooltip
*/
title : null,
/**
* @cfg {String} html The html to show in the tooltip
*/
html : null,
/**
* @cfg {Array} offset The offset to show in the tooltip, [x, y]
*/
offset : null,

init : function(field) {
field.on({
scope : this,
focus : this.onFocus,
blur : this.onBlur
});
},

onFocus : function(field) {
var tip = this.getTip();

!tip.rendered && tip.render(document.body);

tip.showBy(field.el, 'l-r?', this.offset);
},

onBlur : function() {
var tip = this.getTip();

tip.hide();
},

getTip : function() {
var tip = this._tip;

if (!tip) {
tip = this._tip = new Ext.tip.ToolTip({
html : this.html,
title : this.title,
autoHide : false,
showBy : function (el, pos, offset) {
this.showAt(this.getAlignToXY(el, pos || this.defaultAlign, offset));
}
});
}

return tip;
},

destroy : function() {
this._tip.destroy();

delete this._tip;

this.callParent();
}
});

Ext.application({
name : 'Test',

launch : function() {

new Ext.form.Panel({
renderTo : document.body,
title : 'Test',
width : 400,
items : [
{
xtype : 'textareafield',
fieldLabel : 'Test',
anchor : '100%',
plugins : [
{
ptype : 'myplugin',
html : 'This is some foo text',
offset : [0, -10]
}
]
},
{
xtype : 'textfield',
fieldLabel : 'Test',
anchor : '100%',
plugins : [
{
ptype : 'myplugin',
title : 'Test Title',
html : 'This is some foo text',
offset : [0, -20]
}
]
}
]
});

}
});

Jangla
26 Mar 2013, 2:45 AM
Same result. Here (http://jsfiddle.net/CjC3L/) in JS Fiddle.