J'ai une durée avec des données dynamiques dans ma page qui contiennent des Ellipsis. Sens:
<span style='text-overflow: Ellipsis; overflow : hidden; white-space: nowrap;
width: 71;'>${myData}</span>
et j'aimerais ajouter à cette info-bulle d'élément le même contenu (title = '$ {myData}'), mais je souhaite qu'il n'apparaisse que lorsque le contenu est long et que les ellipses apparaissent à l'écran.
Y a-t-il un moyen de le faire?
une direction - lorsque le navigateur (IE dans mon cas) dessine Ellipsis- lance-t-il un événement à ce sujet?
Voici une méthode qui utilise le paramètre Ellipsis intégré et ajoute l'attribut title
à la demande (avec jQuery) à partir du commentaire de Martin Smith:
$('.mightOverflow').bind('mouseenter', function(){
var $this = $(this);
if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
$this.attr('title', $this.text());
}
});
Voici une solution CSS pure. Pas besoin de jQuery. Aucune info-bulle ne sera affichée, mais le contenu du fichier sera agrandi au passage de la souris.
Fonctionne très bien si le contenu est remplacé. Ensuite, vous ne devez pas exécuter une fonction jQuery à chaque fois.
.might-overflow {
text-overflow: Ellipsis;
overflow : hidden;
white-space: nowrap;
}
.might-overflow:hover {
text-overflow: clip;
white-space: normal;
Word-break: break-all;
}
la réponse de uosɐſ est fondamentalement correcte, mais vous ne voulez probablement pas le faire dans l'événement mouseenter. Cela va faire faire le calcul pour déterminer si c'est nécessaire, chaque fois que vous survolez l'élément. À moins que la taille de l'élément change, il n'y a aucune raison de le faire.
Il serait préférable d'appeler ce code immédiatement après l'ajout de l'élément au DOM:
var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
$ele.attr('title', $ele.text());
Ou, si vous ne savez pas exactement quand il est ajouté, appelez ce code une fois le chargement de la page terminé.
si vous avez besoin de plus d'un élément pour le faire, vous pouvez leur donner la même classe (telle que "mightOverflow") et utiliser ce code pour les mettre à jour tous:
$('.mightOverflow').each(function() {
var $ele = $(this);
if (this.offsetWidth < this.scrollWidth)
$ele.attr('title', $ele.text());
});
Voici mon plugin jQuery:
(function($) {
'use strict';
$.fn.tooltipOnOverflow = function() {
$(this).on("mouseenter", function() {
if (this.offsetWidth < this.scrollWidth) {
$(this).attr('title', $(this).text());
} else {
$(this).removeAttr("title");
}
});
};
})(jQuery);
Usage:
$("td, th").tooltipOnOverflow();
Modifier:
J'ai fait un Gist pour ce plugin. https://Gist.github.com/UziTech/d45102cdffb1039d4415
Nous devons détecter si Ellipsis est vraiment appliqué, puis afficher une info-bulle pour révéler le texte intégral. Il ne suffit pas de comparer "this.offsetWidth < this.scrollWidth
" lorsque l'élément contient presque tout son contenu, mais il ne manque que la largeur d'un ou deux pixels, en particulier pour le texte composé de caractères chinois/japonais/coréen pleine largeur.
Voici un exemple: http://jsfiddle.net/28r5D/5/
J'ai trouvé un moyen d'améliorer la détection des ellipses:
this.offsetWidth < this.scrollWidth
", passez à l'étape 2 en cas d'échec.Voici mon amélioration: http://jsfiddle.net/28r5D/6/
J'ai créé un plugin jQuery qui utilise l'info-bulle de Bootstrap au lieu de l'info-bulle intégrée du navigateur. Veuillez noter que cela n'a pas été testé avec un navigateur plus ancien.
JSFiddle: https://jsfiddle.net/0bhsoavy/4/
$.fn.tooltipOnOverflow = function(options) {
$(this).on("mouseenter", function() {
if (this.offsetWidth < this.scrollWidth) {
options = options || { placement: "auto"}
options.title = $(this).text();
$(this).tooltip(options);
$(this).tooltip("show");
} else {
if ($(this).data("bs.tooltip")) {
$tooltip.tooltip("hide");
$tooltip.removeData("bs.tooltip");
}
}
});
};
Voici deux autres solutions CSS pures:
.overflow {
overflow: hidden;
-ms-text-overflow: Ellipsis;
text-overflow: Ellipsis;
white-space: nowrap;
}
.overflow:hover {
overflow: visible;
}
.overflow:hover span {
position: relative;
background-color: white;
box-shadow: 0 0 4px 0 black;
border-radius: 1px;
}
<div>
<span class="overflow" style="float: left; width: 50px">
<span>Long text that might overflow.</span>
</span>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>
.wrap {
position: relative;
}
.overflow {
white-space: nowrap;
overflow: hidden;
text-overflow: Ellipsis;
pointer-events:none;
}
.overflow:after {
content:"";
display: block;
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 15px;
z-index: 1;
border: 1px solid red; /* for visualization only */
pointer-events:initial;
}
.overflow:hover:after{
cursor: pointer;
}
.tooltip {
/* visibility: hidden; */
display: none;
position: absolute;
top: 10;
left: 0;
background-color: #fff;
padding: 10px;
-webkit-box-shadow: 0 0 50px 0 rgba(0,0,0,0.3);
opacity: 0;
transition: opacity 0.5s ease;
}
.overflow:hover + .tooltip {
/*visibility: visible; */
display: initial;
transition: opacity 0.5s ease;
opacity: 1;
}
<div>
<span class="wrap">
<span class="overflow" style="float: left; width: 50px">Long text that might overflow</span>
<span class='tooltip'>Long text that might overflow.</span>
</span>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>
C'est ce que j'ai fait. La plupart des scripts d'info-bulle nécessitent l'exécution d'une fonction qui stocke les info-bulles. Voici un exemple jQuery:
$.when($('*').filter(function() {
return $(this).css('text-overflow') == 'Ellipsis';
}).each(function() {
if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
$(this).attr('title', $(this).text());
}
})).done(function(){
setupTooltip();
});
Si vous ne voulez pas vérifier Ellipsis css, simplifiez-vous comme ceci:
$.when($('*').filter(function() {
return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
$(this).attr('title', $(this).text());
})).done(function(){
setupTooltip();
});
J'ai le "quand" autour, de sorte que la fonction "setupTooltip" ne s'exécute pas tant que tous les titres n'ont pas été mis à jour. Remplacez le "setupTooltip", par la fonction info-bulle et le * par les éléments à vérifier. * passera par tous si vous le laissez.
Si vous voulez simplement mettre à jour les attributs de titre avec l'info-bulle du navigateur, vous pouvez simplifier comme ceci:
$('*').filter(function() {
return $(this).css('text-overflow') == 'Ellipsis';
}).each(function() {
if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
$(this).attr('title', $(this).text());
}
});
Ou sans chèque pour Ellipsis:
$.when($('*').filter(function() {
return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
$(this).attr('title', $(this).text());
});
Si vous voulez faire cela uniquement en utilisant javascript, je voudrais faire ce qui suit. Attribuez à l'attribut span un identifiant (afin qu'il puisse être facilement extrait du DOM) et placez tout le contenu dans un attribut nommé 'contenu':
<span id='myDataId' style='text-overflow: Ellipsis; overflow : hidden;
white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>
Ensuite, dans votre javascript, vous pouvez effectuer les opérations suivantes une fois l’élément inséré dans le DOM.
var elemInnerText, elemContent;
elemInnerText = document.getElementById("myDataId").innerText;
elemContent = document.getElementById("myDataId").getAttribute('content')
if(elemInnerText.length <= elemContent.length)
{
document.getElementById("myDataId").setAttribute('title', elemContent);
}
Bien entendu, si vous utilisez du javascript pour insérer la plage dans le DOM, vous pouvez simplement conserver le contenu dans une variable avant de l'insérer. De cette façon, vous n'avez pas besoin d'un attribut de contenu sur la durée.
Il existe des solutions plus élégantes que cela si vous souhaitez utiliser jQuery.
J'ai la classe CSS, qui détermine où mettre Ellipsis. En fonction de cela, je fais ce qui suit (le jeu d’éléments peut être différent, j’écris ceux dans lesquels Ellipsis est utilisé, bien sûr il pourrait s’agir d’un sélecteur de classe séparé):
$(document).on('mouseover', 'input, td, th', function() {
if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
$(this).attr('title', $(this).val());
}
});
C'était ma solution, fonctionne comme un charme!
$(document).on('mouseover', 'input, span', function() {
var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
if (needEllipsis === true) {
if(hasNotTitleAttr === true){
$(this).attr('title', $(this).val());
}
}
if(needEllipsis === false && hasNotTitleAttr == false){
$(this).removeAttr('title');
}
});
Vous pouvez éventuellement entourer l'envergure d'une autre étendue, puis simplement tester si la largeur de l'envergure d'origine/intérieure est supérieure à celle de la nouvelle étendue/extérieure. Notez que je dis éventuellement - c'est en gros basé sur ma situation où j'avais un span
à l'intérieur d'un td
alors je ne sais pas vraiment si cela fonctionnera avec un span
à l'intérieur d'un span
.
Voici cependant mon code pour les autres qui pourraient se retrouver dans une position similaire à la mienne; Je le copie/le colle sans le modifier même s’il se trouve dans un contexte Angular, je ne pense pas que cela nuise à la lisibilité et au concept essentiel. Je l'ai codé en tant que méthode de service car je devais l'appliquer à plusieurs endroits. Le sélecteur que j'ai transmis est un sélecteur de classe qui correspond à plusieurs instances.
CaseService.applyTooltip = function(selector) {
angular.element(selector).on('mouseenter', function(){
var td = $(this)
var span = td.find('span');
if (!span.attr('tooltip-computed')) {
//compute just once
span.attr('tooltip-computed','1');
if (span.width() > td.width()){
span.attr('data-toggle','tooltip');
span.attr('data-placement','right');
span.attr('title', span.html());
}
}
});
}
Aucune des solutions ci-dessus n'a fonctionné pour moi, mais j'ai trouvé une excellente solution. La plus grande erreur que font les gens est d'avoir toutes les 3 propriétés CSS déclarées sur l'élément lors du chargement de page. Vous devez ajouter ces styles + info-bulle de manière dynamique SI et UNIQUEMENT SI la plage sur laquelle vous souhaitez une ellipses est plus large que son parent.
$('table').each(function(){
var content = $(this).find('span').text();
var span = $(this).find('span');
var td = $(this).find('td');
var styles = {
'text-overflow':'Ellipsis',
'white-space':'nowrap',
'overflow':'hidden',
'display':'block',
'width': 'auto'
};
if (span.width() > td.width()){
span.css(styles)
.tooltip({
trigger: 'hover',
html: true,
title: content,
placement: 'bottom'
});
}
});
Voici une solution JavaScript Vanille:
(function init() {
var cells = document.getElementsByClassName("cell");
for(let index = 0; index < cells.length; ++index) {
let cell = cells.item(index);
cell.addEventListener('mouseenter', setTitleIfNecessary, false);
}
function setTitleIfNecessary() {
if(this.offsetWidth < this.scrollWidth) {
this.setAttribute('title', this.innerHTML);
}
}
})();
.cell {
white-space: nowrap;
overflow: hidden;
text-overflow: Ellipsis;
border: 1px;
border-style: solid;
width: 120px;
}
<div class="cell">hello world!</div>
<div class="cell">hello mars! kind regards, world</div>