est-il possible que jQuery/javascript détecte où une chaîne est cassée (afin de tenir dans les contraintes de largeur CSS) afin d'insérer des éléments DOM avant le début d'une nouvelle ligne?
Je suis venu avec une approche, mais il pourrait être exagéré pour vos objectifs, alors prenez cela en compte.
Vous devez créer un clone de l'élément, vider l'original, puis replacer chaque mot dans l'élément d'origine. Si la hauteur change en tout point, il y a un saut de ligne avant ce mot. Ce serait assez simple à faire avec $(el).text()
, mais cela devient plus compliqué s'il peut y avoir d'autres balises à l'intérieur, pas seulement du texte. J'ai essayé d'expliquer comment le décomposer par nœud dans cette boîte de réponse, mais j'ai trouvé plus facile de créer un plugin jQuery dans un jsFiddle. Lien ici: http://jsfiddle.net/nathan/qkmse/ ( Gist ).
Il ne supportera pas très bien les éléments flottants, et il y a quelques autres situations où il va tomber. Faites-moi savoir si vous souhaitez plus d'options, ou si cela ne fonctionne pas tout à fait pour vos besoins, ou si vous ne savez pas comment l'appliquer et je vais essayer de vous aider.
Voici une approche. Remarque: je ne vois pas de solution idéale sans utiliser des polices monospaces. L'égalité avec les personnages facilite beaucoup cette tâche.
Regardez le jsfiddle pour le code HTML associé. Je n'ai pas terminé cette fonction. Davantage de contrôles doivent être mis en place lors du calcul de l'indice de rupture. À l'heure actuelle, il utilise lastIndexOf (''), mais cela ignore que l'index suivant pourrait être un espace, ou le courant. De plus, je ne comptabilise pas d'autres caractères de rupture de ligne. Cependant, cela devrait être un excellent point de départ.
var text = $('#text').text(), // "lorem ipsum ... "
len = text.length, // total chars
width = $('#text').width(), // container width
span = $('<span />').append('a').appendTo('#sandbox'),
charWidth = span.width(), // add single character to span and test width
charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row
var breakingIndexes = [], // will contain indexes of all soft-breaks
gRowStart = 0, // global row start index
gRowEnd = charsPerRow;// global row end index
while(gRowEnd < len){
var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
breakingIndexes.Push(gRowStart + rowEnd); // add breaking index to array
gRowStart = gRowStart + rowEnd + 1; // next start is the next char
gRowEnd = gRowStart + charsPerRow; // global end inxex is start + charsperrow
}
var text2 = $('#text2').text(); // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
start = breakingIndexes[i]; // update start
}
$('#text2').html(newText); // output with breaks
ceci est mon script, qui prend du texte, puis fait de chaque ligne une durée
CSS:
margin: 0;
padding: 0;
}
.title{
width: 300px;
background-color: rgba(233,233,233,0.5);
line-height: 20px;
}
span{
color: white;
background-color: red;
display: inline-block;
font-size: 30px;
}
a{
text-decoration: none;
color: black;
}
html
<div class="title">
<a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
</div>
JS
$(function(){
$(".title").find("a").each(function(){
var $this = $(this);
var originalText = $this.text();
$this.empty();
var sections = [];
$.each( originalText.split(" "), function(){
var $span = $("<span>" + this + "</span>");
$this.append($span);
var index = $span.position().top;
if( sections[index] === undefined ){
sections[index] = "";
}
sections[index] += $span.text() + " ";
});
$this.empty();
for(var i = 0; i< sections.length; i++){
if( sections[i] !== undefined ){
var spanText = $.trim(sections[i]);
$this.append("<span>" + spanText + "</span>");
}
}
});
});
Vous devez avoir jQuery inclus.
Je ne connais pas de fonction javascript intégrée à jQuery pour le faire. Vous pouvez toutefois le faire vous-même, mais ce serait potentiellement lent si vous avez beaucoup de texte.
En théorie, vous pouvez vous assurer que la hauteur est définie sur auto, supprimez le texte, puis Word par Word, puis réinsérez-le. Lors d'un changement de hauteur, vous supprimez le dernier mot et insérez votre élément dom. Encore une fois, cela sera lent s'il y a beaucoup de texte, et le meilleur moyen de le faire serait de ne pas changer l'élément d'origine, mais de le faire dans un autre élément pouvant être masqué, puis de remplacer l'élément d'origine à la fin. De cette façon, votre utilisateur ne verrait pas le contenu disparaître, puis reviendrait mot par mot.
Une autre méthode consisterait à utiliser un principe similaire et à commencer par un élément vide de même taille avec height auto, puis à insérer un nouveau caractère et un espace jusqu'à obtenir une nouvelle ligne. À partir de là, vous pouvez utiliser ceci comme approximation de la technologie ci-dessus ou vous pouvez ajouter aveuglément la longueur de chaque chaîne jusqu'à ce que vous trouviez une nouvelle ligne, en tenant compte de la largeur de votre élément dom. Cependant, cette technique fonctionne mieux avec les polices à espacement fixe. C’est pourquoi l’utiliser uniquement à titre approximatif.
Cela dit, il existe un moyen de mesurer le texte à l’aide de canvas, mais cela peut être extrême. En théorie, créer un élément de structure, obtenir le contexte, définir toutes les propriétés de la police, puis utiliser la méthode context.measureText()
. Un exemple d'utilisation peut être trouvé here .
Vous pouvez également comparer la largeur du bloc de texte à la largeur de son parent. Si le bloc mesure au moins 98% de la largeur de son parent, il est presque certain qu'il casse
Je pense qu'il serait plus facile de détecter en utilisant une regex - beaucoup moins de code tout en conservant l'efficacité.
Voici quelque chose qui a fonctionné pour moi:
if ((/(\r\n|\n|\r)/.test($(this).val()))) {
alert('there are line breaks here')
}
Je ne sais pas si cela fonctionnera avec vos chaînes cassées, mais cela fonctionne pour détecter les sauts de ligne avec jQuery.
Vous ne savez pas exactement quel est votre cas d'utilisation, mais http://code.google.com/p/hyphenator/ peut être une solution à votre problème ou si vous creusez dans le code source de hyphenator.js, vous pourrez peut-être pour trouver le code que vous recherchez.