Ainsi, chaque fois que je charge un Bootstrap Popover avec une option content
vide et que je l'insère de manière dynamique, le popover perd sa position correcte.
Par exemple:
$('td.chartSection').each(function () {
var $thisElem = $(this);
$thisElem.popover({
placement: 'top',
trigger: 'hover',
html: true,
container: $thisElem,
delay: {
hide: 500
},
content: ' '
});
});
//After popup is shown, run this event
$('td.chartSection').on('shown.bs.popover', function () {
var $largeChart = $(this).find('.popover .popover-content');
//Insert some dummy content
$largeChart.html("dfjhgqrgf regqef f wrgb wrbgqwtgtrg <br /> wfghjqerghqreg fbvwqbtwfbvfgb <br />efgwetrg");
});
Ma question:
Existe-t-il une méthode permettant de recalculer la position de popovers telle que $('td.chartSection').popover('recalculate')
.
Ou existe-t-il un autre moyen de repositionner le popover sans le faire manuellement avec les styles CSS?
Non, il n'y a pas de recalcul et il n'y a vraiment pas de moyen facile de le faire. Cela dit, vous pouvez injecter dynamiquement les popovers de cette façon:
$('td.chartSection').on('mouseenter', function() {
var myPopOverContent = 'This is some static content, but could easily be some dynamically obtained data.';
$(this).data('container', 'body');
$(this).data('toggle', 'popover');
$(this).data('placement', 'top');
$(this).data('content', myPopOverContent);
$(this).popover('show');
});
$('td.chartSection').on('mouseout', function() {
$(this).popover('hide');
});
Il suffit de remplacer tous vos js dans votre violon avec ce qui précède et de le vérifier ...
En utilisant Bootstrap v3.3.7:
Vous pouvez étendre le constructeur Popover pour prendre en charge une fonction de repositionnement. Vous pouvez placer ce script ci-dessous à l'endroit où vous chargez bootstrap.
<script src="bootstrap.js"></script>
<script type="text/javascript">
$(function () {
$.fn.popover.Constructor.prototype.reposition = function () {
var $tip = this.tip()
var autoPlace = true
var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var orgPlacement = placement
var viewportDim = this.getPosition(this.$viewport)
placement = placement === 'bottom' &&
pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement === 'top' &&
pos.top - actualHeight < viewportDim.top ? 'bottom' : placement === 'right' &&
pos.right + actualWidth > viewportDim.width ? 'left' : placement === 'left' &&
pos.left - actualWidth < viewportDim.left ? 'right' : placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
}
})
</script>
Puis, dans votre script, chaque fois que vous devez repositionner votre info-bulle après avoir inséré du contenu. Vous pouvez simplement appeler:
$element.popover('reposition')
Je viens d'appeler
button.popover('show');
Et ça le repositionne.
J'ai eu une situation similaire où j'avais un popover qui contenait déjà du HTML (un spinner de chargement) et je changeais le contenu quand un appel ajax est revenu. Dans ma fonction de rappel ajax, c’était le code que j’avais utilisé pour changer le positionnement, de sorte qu’il restait centré:
var originalHeight = $(popover).height();
$(popover).find('.popover-content').html(data);
var newHeight = $(popover).height();
var top = parseFloat($(popover).css('top'));
var changeInHeight = newHeight - originalHeight;
$(popover).css({ top: top - (changeInHeight / 2) });
J'ai utilisé ce code pour ajuster la hauteur du popover lorsqu'il est déjà chargé dans la page:
var popover = $(this).closest('.popover');
var sender = popover.prev();
var adjustment = (sender.position().top - popover.height()) + 15;
popover.css({ top: adjustment });
Variable sender est la cible depuis laquelle le popover est centré.
Si la position du popover est "haut" (comme dans la question), vous pouvez simplement ajuster son positionnement absolu à partir du haut de la page.
J'ai créé une fonction permettant de calculer la hauteur du popover, puis de la déplacer vers le haut de la page en fonction de sa hauteur.
function adjustPopoverHeight($popoverElement) {
var height = $popoverElement.height();
var adjustment = 0 - height - 4;
$popoverElement.css({ top: adjustment });
}
et utiliser avec une requête ajax pour obtenir des données:
$.ajax({
type: 'GET',
url: url,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).done(function(dat) {
//set the popover content to whatever you like
//adjust height of popover
var $popoverElement = $('.popover');
adjustPopoverHeight($popoverElement);
})
J'ai pris le concept de la réponse de jme11 et mis à jour pour Bootstrap 3.3.2+
$('button')
.popover({
trigger: 'manual',
html: true,
container: 'body',
})
.click(function() {
var $this = $(this);
var popover_obj = $this.data('bs.popover');
if (popover_obj.tip().hasClass('in')) {
popover_obj.hide();
} else {
var opts = popover_obj.options;
opts.content = $('<div/>').text('hello world');
popover_obj.init('popover', $this, opts);
popover_obj.show();
}
})
;
Il existe une méthode appelée setContent sur l'objet popover, mais pour une raison quelconque, cela ne fonctionnait pas pour moi. Si vous souhaitez essayer, cela ressemblerait à ceci:
popover_obj.setContent($('<div/>').text('hello world'));
ceci est inspiré par la réponse de @AlexCheuk ci-dessus, mais j'avais besoin d'une solution utilisant Bootstrap 2 . De plus, dans mon projet, je n'avais pas besoin de changer le placement des popovers, alors je l'ai éliminé.
$(function() {
$.fn.popover.Constructor.prototype.reposition = function () {
console.log('popover reposition is called');
var $tip = this.tip();
var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;
var pos = this.getPosition();
var actualWidth = $tip[0].offsetWidth;
var actualHeight = $tip[0].offsetHeight;
function getCalculatedOffset (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width };
}
var calculatedOffset = getCalculatedOffset(placement, pos, actualWidth, actualHeight);
this.applyPlacement(calculatedOffset, placement);
console.log(this);
};
});
Pour l'appeler:
$element.popover('reposition')