Hide bootstrap tooltip instead of disposing - javascript

Is there any way we can hide bootstrap tool-tips instead of destroying them.
I am using server side data in tool-tips and I don't want to load data every time a tool-tip is initiated.
$('.selector').popover({
animation: true,
trigger: 'click',
title: 'Notifications',
content: 'No new notificaitons',
placement: 'right',
container: 'body',
html: true,
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js" integrity="sha384-u/bQvRA/1bobcXlcEYpsEdFVK/vJs3+T+nXLsBYJthmdBuavHvAW6UsmqO2Gd/F9" crossorigin="anonymous"></script>
<span class="selector">selector</span>

You don't have to hide your tooltip, you have an other way.
You can load your server side data in a global object and use this object when you open your tooltip.
In this case, your data is load only one times, and you don't have to change the tooltip.
Example :
var myObject = {};
$.get(PHP_PAGE, DATAS).done(function(data){
//HERE GET YOUR DATA LIKE
myObject = data;
});
...
$('.selector').popover({
animation: true,
trigger: 'click',
title: myObject.title,
content: myObject.contentMessage,
placement: 'right',
container: 'body',
html: true,
})

Related

tippy tooltip position with browser zoom in/out

I have made a popover with tippyjs. Tippy takes next options:
const tippyInstance: any = tippy(element, {
content: loaderTemplate,
placement: 'right',
animation: 'fade',
animateFill: false,
theme: 'kpi-tooltip',
trigger: 'manual',
interactive: true,
onHidden: () => {
tippyInstance.destroy();
},
allowHTML: true
});
"Element" is a plain html element and content loading after response from server. The problem is when i make browser zoom in or zoom out the tooltips changes position. I'm using chrome last version.
Tooltip in normal state:
Tooltip with zoom in:
"appendTo" property option solved the problem.

Is it possible to make multiple Bootstrap popovers more DRY?

I've run into a problem, where I have more than 10 popovers in one table. They all should display a popover on hover, and have a similar html, but with some differences in content. I made it the easiest way, but I feel there must be a smarter way to do this.
Is it possible to make this js code more DRY?
$('#static-pop-1').popover({
'trigger': 'hover',
'placement': 'bottom',
'html': true,
'content': '<div class="static-popover"><span>Hey!</span></div>'
});
$('#static-pop-2').popover({
'trigger': 'hover',
'placement': 'bottom',
'html': true,
'content': '<div class="static-popover"><span>Hey 2!</span></div>'
});
http://jsfiddle.net/axt63orn/
Assuming you don't want the popover to just say Hey 1, Hey 2 etc. but actually set a different content in each, but keep the rest of the settings the same, you can do
var settings = {
trigger : 'hover',
placement : 'bottom',
html : true
}
$('#static-pop-1').popover($.extend({}, settings, {
content: '<div class="static-popover"><span>Hey!</span></div>'
}));
$('#static-pop-2').popover($.extend({}, settings, {
content: '<div class="static-popover"><span>Hey 2!</span></div>'
}));
$('#static-pop-3').popover($.extend({}, settings, {
content: '<div class="static-popover"><span>Hey 3!</span></div>'
}));
FIDDLE
or you could use a function
function setting(text) {
return {
trigger : 'hover',
placement : 'bottom',
html : true,
content : '<div class="static-popover"><span>'+text+'</span></div>'
}
}
$('#static-pop-1').popover(setting('Hey!'));
$('#static-pop-2').popover(setting('Hey 2!'));
$('#static-pop-3').popover(setting('Hey 3!'));
FIDDLE
You could use data attribute:
<a class="pop" id="static-pop-1" data-mycontent="Hey 1!" title="">Content 1</a>
$('.pop').popover({
'trigger': 'hover',
'placement': 'bottom',
'html': true,
'content': function(){
return '<div class="static-popover"><span>'+$(this).data('mycontent')+'</span></div>';
}
});
JSFiddle

jQuery does not work when reload the page content via ajax

I use Bootstrap to display a popover, until there is with all this code below everything works normal.
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
I only need to load the content of the page via ajax, then I changed the code because when I load the content dynamically I need to delegate events, changed the code and it looked like this:
$('body').on('click','.emoticons',function()
{
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
});
Now my troubles started. The code works however when I click the first time it does not work, so it works when I click more than once on the link. What to do?
What's happening is that when you are clicking on the .emoticons and executing your popover function, it is at that moment that you are binding it to your click. That's why it doesn't work the first time, but it works afterwards. It starts listening to the click event after that.
Ideally, the solution is to run the .popover function when the new content is loaded (on your AJAX callback).
If you want to just copy paste my code and see if it works, you can do this:
$('body').on('click','.emoticons',function()
{
// Convert this element into a popover and then display it
$(this).popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {
return $('.emoticonimg').html();
}
}).popover('toggle');
});
But, I would NOT recommend this code specifically, since you are re-initializing your popover every time you click on it.
It's better and more clear if you bind all popovers after your AJAX request is done:
$.ajax( "BlaBlaBla.php" )
.done(function() {
// Convert all emoticons to popovers
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {
return $('.emoticonimg').html();
}
});
});
It doesn't work the first time because the first click if firing off the body onclick handler which binds your popover.
Try something like this in your $(document).ready() function.
$(".emoticons").click(function(){
$(this).popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
});

extjs displaying loadmask on panel when store loads

I added a loadmask to a panel and I want the spinner to be displayed each time stores associated with the loadmask are loaded. The panel is a large tooltip and the stores are loaded each time a point is visited in a line chart. Thus, when I hover over a point, I'm expecting a load message to appear for a short period of time before I see the contents in the panel. What I'm getting is an empty panel however. If I remove the code that I have which adds the load mask (the initComponent function), it works (without the load message though). How would I use the loadmask in this manner as opposed to explicitly calling the setLoading() method for each panel?
Here's the code:
tips:
{
...
items:{
xtype: 'panel',
initComponent: function(){
var loadMask = new Ext.LoadMask(this, {
store: Ext.getStore('CompanyContext')
});
},
id: 'bar-tip-panel',
width: 700,
height: 700,
layout: {
type: 'accordion',
align : 'stretch',
padding: '5 5 5 5'
},
items:...
}
}
config object isn't the proper place to override initComponent method. What you should do is to define a subclass of Panel, and override the method there.
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',
xtype: 'mypanel',
initComponent: function() {
this.callParent(arguments); // MUST call parent's method
var loadMask = new Ext.LoadMask(this, {
store: ...
});
},
});
Then, you can use xtype mypanel in your tips configuration.

ExtJS renderTo element not found

I have an MVC architecture, but when I try to make another TabPanel insite an existing one, I get this in the browser:
el is null
el = el.dom || Ext.getDom(el); ext-all-debug.js (line 12807)
From what I understand, it seems that the new TabPanel can't find the needed div for it to render. Anyway, here is the controller:
Ext.define('FI.controller.MainController', {
extend: 'Ext.app.Controller',
id: 'mainController',
views: ['MainTabPanel', 'UnitsTabPanel', 'SummariesTabPanel'],
mainTabPanel : {},
unitsTabPanel : {},
summariesTabPanel : {},
init: function(){
console.log("main controller is init");
console.log(this);
this.control({
'mainTabPanel':{
afterrender: this.onCreate
}
});
this.mainTabPanel = Ext.widget('mainTabPanel');
},
onCreate: function(){
console.log("main tab panel is created");
console.log(this);
this.unitsTabPanel = Ext.widget('unitsTabPanel');
this.summariesTabPanel = Ext.widget('summariesTabPanel');
}
});
This is the MainTabPanel:
Ext.define("FI.view.MainTabPanel", {
extend: 'Ext.tab.Panel',
renderTo:'container',
alias: 'widget.mainTabPanel',
enableTabScroll: true,
items:[{
title:'Units',
html: "<div id='units'></div>",
closable: false
},
{title: 'Summaries',
html: "<div id='summaries'></div>",
closable:false
}
]
});
And this is the SummariesTabPanel(the one with problems):
Ext.define("FI.view.SummariesTabPanel", {
extend: 'Ext.tab.Panel',
renderTo: 'summaries',
alias: 'widget.summariesTabPanel',
enableTabScroll: true
});
The problem is with the SummariesTabPanel. If I don't create it, the UnitsTabPanel gets rendered. For some reason, it can't find the summaries div.
Can you please tell me what is wrong?
The SummariesTabPanel renders to the "units" div according to your last snippet of code, is that correct? If not, replace renderTo: 'units' with renderTo: 'summaries'.
Edit
Since it was not the case, you may take a look ath this piece of Ext 4 Panel documentation (here: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.panel.Panel-cfg-html ) that says that the html content isn't added until the component is completely rendered. So, you have to wait for the afterrender event of the tab (not the tabpanel, as you do now) before you can actually get the DOM element.
If you instantiate this Panel
{title: 'Summaries',
html: "<div id='summaries'></div>",
closable:false
}
and store the pointer to it into a separate variable, you could listen to its afterrender event and try again.
A workaround to this could be using an existing element of the page (that is, a static html fragment) instead of adding it via the Panel's html config option.
Why are you doing this that way? If you want to have a nested panels - just define them inside one another. Don't use renderTo
Ext.define("FI.view.SummariesTabPanel", {
extend: 'Ext.tab.Panel',
alias: 'widget.summariesTabPanel'
});
Ext.define("FI.view.MainTabPanel", {
extend: 'Ext.tab.Panel',
alias: 'widget.mainTabPanel',
enableTabScroll: true,
items:[{
xtype: 'summariesTabPanel'
title:'Units',
closable: false
}
]
});

Categories