Calcul de la largeur du texte

101

J'essaye de calculer la largeur du texte en utilisant jQuery. Je ne sais pas quoi, mais je fais définitivement quelque chose de mal.

Alors, voici le code:

var c = $('.calltoaction');

var cTxt = c.text();

var cWidth =  cTxt.outerWidth();

c.css('width' , cWidth);
Dom
la source
Alors, de quelle manière ce code ne fonctionne-t-il pas? Que doit-il faire différemment?
Sixten Otto

Réponses:

142

Cela a mieux fonctionné pour moi:

$.fn.textWidth = function(){
  var html_org = $(this).html();
  var html_calc = '<span>' + html_org + '</span>';
  $(this).html(html_calc);
  var width = $(this).find('span:first').width();
  $(this).html(html_org);
  return width;
};
Rune Kaagaard
la source
4
+1 - cela mesure vraiment le texte, pas seulement l'élément de bloc contenant comme la solution de brainreavis.
Ben
Nappe. +1. Il semble que vous manquez un point-virgule sur la troisième ligne après '</span>', bien que cela ne semble pas faire de différence (travaillé avec ou sans lui sur FF9).
shmeeps
21
Soyez prudent avec ceci cependant ... cette méthode dissociera tous les événements sur les éléments enfants.
brianreavis
J'ai essayé d'utiliser cette fonction de plusieurs manières, mais elle renvoie toujours null. Quelqu'un pourrait-il s'il vous plaît poster la syntaxe de la façon dont cette fonction est réellement utilisée? Dois-je exécuter la fonction .textWidth () sur un objet jQuery? Dois-je passer du texte à cette fonction? Dois-je exécuter la fonction en tant que fonction jQuery (c'est-à-dire $ .textWidth (jqObject)? Parce qu'aucune de ces options ne semble fonctionner. Merci ...
moosefetcher
2
@moosefetcher vous feriez $ (selector) .textWidth (); Regardez ici learn.jquery.com/plugins/basic-plugin-creation/…
uesports135
89

Voici une fonction qui est meilleure que d'autres publiées car

  1. c'est plus court
  2. cela fonctionne lors du passage d' un <input>, <span>ou "string".
  3. il est plus rapide pour les utilisations fréquentes car il réutilise un élément DOM existant.

Démo: http://jsfiddle.net/philfreo/MqM76/

// Calculate width of text from DOM element or string. By Phil Freo <http://philfreo.com>
$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};
philfreo
la source
1
Hou la la! Absolument génial!
Michel Triana
3
Excellente solution, devrait être réponse acceptée, je pense! Merci mon pote!
Ilia Rostovtsev
Fantastico! Simple et propre.
Carey Estes
Bien que bon, cela ne gère pas les espaces. Voir la réponse de @ edsioufi pour une amélioration de cette solution.
Badgerspot
S'il y a du texte caché à l'intérieur de l'élément, cela faussera votre largeur. Pour tenir compte de cela, assurez-vous de supprimer les nœuds masqués avant de calculer la largeur du texte. Pour supprimer en toute sécurité les nœuds cachés, vous devez probablement d'abord créer un clone et effectuer la suppression à cet endroit.
thdoan
36

Ma solution

$.fn.textWidth = function(){
    var self = $(this),
        children = self.children(),
        calculator = $('<span style="display: inline-block;" />'),
        width;

    children.wrap(calculator);
    width = children.parent().width(); // parent = the calculator wrapper
    children.unwrap();
    return width;
};

Fondamentalement, une amélioration par rapport à Rune, qui n'utilise pas .htmlsi légèrement

bevacqua
la source
Par Ajarn Gerhard qui a posté ceci comme réponse: Cela ne fonctionne pas dans IE8 car il vous manque un /avant le crochet fermant du <span>tag:calculator = $('<span style="display: inline-block;" />'),
Petr R.
1
Cela semble renvoyer null s'il y a un élément enfant sous l'élément que vous mesurez. Peut-il fonctionner sans l'élément enfant? Voir jsfiddle.net/h22tj/41
Casper
+1 - Je n'ai jamais su qu'il y avait eu un déballage (), qui m'a causé un chagrin sans fin.
Orwellophile
Il renvoie toujours null sur Chrome.
emeraldhieu
12

Les textWidthfonctions fournies dans les réponses et qui acceptent un stringcomme argument ne prendront pas en compte les espaces blancs de début et de fin (ceux-ci ne sont pas rendus dans le conteneur factice). En outre, ils ne fonctionneront pas si le texte contient un balisage html (une sous-chaîne <br>ne produira aucune sortie et &nbsp;renverra la longueur d'un espace).

Ceci n'est un problème que pour les textWidthfonctions qui acceptent a string, car si un élément DOM est donné et .html()est appelé sur l'élément, alors il n'est probablement pas nécessaire de résoudre ce problème pour un tel cas d'utilisation.

Mais si, par exemple, vous calculez la largeur du texte pour modifier dynamiquement la largeur d'un inputélément de texte au fur et à mesure que l'utilisateur tape (mon cas d'utilisation actuel), vous voudrez probablement remplacer les espaces de début et de fin par &nbsp;et encoder la chaîne en html.

J'ai utilisé la solution de philfreo donc en voici une version qui corrige ce problème (avec des commentaires sur les ajouts):

$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').appendTo(document.body);
    var htmlText = text || this.val() || this.text();
    htmlText = $.fn.textWidth.fakeEl.text(htmlText).html(); //encode to Html
    htmlText = htmlText.replace(/\s/g, "&nbsp;"); //replace trailing and leading spaces
    $.fn.textWidth.fakeEl.html(htmlText).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};
Edsioufi
la source
Merci. Votre réponse est très précieuse.
Vishal
1
Curieusement, lorsque j'ai essayé celui-ci, il n'a pas correctement copié le fichier font-size. J'ai dû ajouter css('font-size'), this.css('font-size'))pour que cela fonctionne. Des idées pourquoi fontseul ne copie pas cette valeur?
Fini le codage le
@GoneCoding Où avez-vous ajouté ces extras?
webmagnets
@webmagnets: Même endroit que la .cssméthode existante , mais je vois que mes crochets sont erronés. Devrait être css('font-size', this.css('font-size')).
Fini le codage le
11

Les fonctions de largeur de jQuery peuvent être un peu floues lorsque vous essayez de déterminer la largeur du texte en raison de modèles de boîte incohérents. Le moyen le plus sûr serait d'injecter div à l'intérieur de votre élément pour déterminer la largeur réelle du texte:

$.fn.textWidth = function(){
  var sensor = $('<div />').css({margin: 0, padding: 0});
  $(this).append(sensor);
  var width = sensor.width();
  sensor.remove();
  return width;
};

Pour utiliser ce mini plugin, il suffit de:

$('.calltoaction').textWidth();
Brianreavis
la source
1
Cela ne vous donnerait-il pas la largeur du bloc plutôt que le texte?
Josh Rickard
-1 Cela semble en effet mesurer la largeur de la boîte plutôt que la largeur du texte.
Nathan Arthur
1
Le simple fait d'utiliser un span au lieu d'un div ne résoudrait-il pas le problème de largeur? Si tel est le cas, cette fonction est un peu meilleure que la réponse acceptée.
Josh
@Josh: Si vous le remplacez par un, spanvous obtenez simplement zéro. H2J'ai essayé cette solution sur un , où les éléments parents ont le débordement masqué, et je n'obtiens que la longueur tronquée du texte. Peut-être qu'une explication de la façon dont cela est censé fonctionner aiderait-elle à mieux le faire?
Fini le codage le
8

J'ai trouvé que cette solution fonctionne bien et qu'elle hérite de la police d'origine avant le dimensionnement:

$.fn.textWidth = function(text){
  var org = $(this)
  var html = $('<span style="postion:absolute;width:auto;left:-9999px">' + (text || org.html()) + '</span>');
  if (!text) {
    html.css("font-family", org.css("font-family"));
    html.css("font-size", org.css("font-size"));
  }
  $('body').append(html);
  var width = html.width();
  html.remove();
  return width;
}
Vince Spicer
la source
1
J'ai fini par utiliser ceci, mais ajouté org.css("font-weight"). Aussi, je dirais que la if(!text)partie n'est pas intuitive. Si j'utilise par exemple, jQuery("#someContainer").textWidth("Lorem ipsum")je voudrais connaître la largeur du texte de "Lorem ipsum" lorsqu'il est appliqué dans ce conteneur particulier.
Sleavely
8

Ni Rune ni Brain ne fonctionnaient pour moi au cas où l'élément qui contenait le texte avait une largeur fixe. J'ai fait quelque chose de similaire à Okamera. Il utilise moins de sélecteurs.

EDIT: Cela ne fonctionnera probablement pas pour les éléments qui utilisent relative font-size, car le code suivant insère l' htmlCalcélément dans bodyainsi perd les informations sur la relation des parents.

$.fn.textWidth = function() {
    var htmlCalc = $('<span>' + this.html() + '</span>');
    htmlCalc.css('font-size', this.css('font-size'))
            .hide()
            .prependTo('body');
    var width = htmlCalc.width();
    htmlCalc.remove();
    return width;
};
chmurson
la source
C'était la meilleure solution pour moi avec le support IE8 et ne rompra aucune liaison avec l'élément dans le processus! THX.
ouija
Remarque: dans une méthode d'extension jQuery, thisest déjà un objet jQuery et $(this)est donc redondant.
Fini le codage le
Cela a mal fonctionné pour moi, car la largeur calculée est trop petite. La réponse acceptée a fonctionné correctement
PandaWood
5

Si vous essayez de faire cela avec du texte dans une boîte de sélection ou si ces deux ne fonctionnent pas, essayez celle-ci à la place:

$.fn.textWidth = function(){
 var calc = '<span style="display:none">' + $(this).text() + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

ou

function textWidth(text){
 var calc = '<span style="display:none">' + text + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

si vous voulez d'abord saisir le texte

okamera
la source
4

la chose que vous faites mal, c'est que vous appelez une méthode sur cTxt, qui est une simple chaîne et non un objet jQuery. cTxt est vraiment le texte contenu.

Juraj Blahunka
la source
2

Légère modification de celle de Nico, car .children () renverra un ensemble vide si nous référençons un élément de texte comme h1 ou p . Nous allons donc utiliser .contents () à la place, et utiliser this au lieu de $ (this) puisque nous créons une méthode sur un objet jQuery.

$.fn.textWidth = function(){
    var contents = this.contents(),
        wrapper  = '<span style="display: inline-block;" />',
        width    = '';

    contents.wrapAll(wrapper);
    width = contents.parent().width(); // parent is now the wrapper
    contents.unwrap();
    return width;
    };
309 concepteur
la source
1

après avoir chassé un fantôme pendant deux jours, en essayant de comprendre pourquoi la largeur d'un texte était incorrecte, j'ai réalisé que c'était à cause des espaces blancs dans la chaîne de texte qui arrêteraient le calcul de la largeur.

donc, une autre astuce est de vérifier si les espaces sont à l'origine de problèmes. utilisation

&nbsp;

espace insécable et voyez si cela résout le problème.

les autres fonctions suggérées fonctionnent bien aussi, mais ce sont les espaces blancs qui causent des problèmes.

zonabi
la source
Ajoutez simplement temporairement white-space: nowraple CSS en ligne pour éviter cela.
Fini le codage le
1

Si vous essayez de déterminer la largeur d'un mélange de nœuds de texte et d'éléments à l'intérieur d'un élément donné, vous devez envelopper tout le contenu avec wrapInner () , calculer la largeur, puis dérouler le contenu.

* Remarque: Vous devrez également étendre jQuery pour ajouter une fonction unwrapInner () car elle n'est pas fournie par défaut.

$.fn.extend({
  unwrapInner: function(selector) {
      return this.each(function() {
          var t = this,
              c = $(t).children(selector);
          if (c.length === 1) {
              c.contents().appendTo(t);
              c.remove();
          }
      });
  },
  textWidth: function() {
    var self = $(this);
    $(this).wrapInner('<span id="text-width-calc"></span>');
    var width = $(this).find('#text-width-calc').width();
    $(this).unwrapInner();
    return width;
  }
});
voyage41
la source
+1 pour .wrapInner. Comme vous le savez probablement, gérer des éléments de texte pur dans jQuery est un enfer. S'il existe d'autres méthodes jQuery applicables, veuillez me le faire savoir. J'ai dû recourir à .get (0) .children et ce n'est pas joli.
Orwellophile
1

Développement de la réponse de @ philfreo:

J'ai ajouté la possibilité de vérifier text-transform, car des choses comme text-transform: uppercaseont généralement tendance à élargir le texte.

$.fn.textWidth = function (text, font, transform) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text())
        .css('font', font || this.css('font'))
        .css('text-transform', transform || this.css('text-transform'));
    return $.fn.textWidth.fakeEl.width();
};
shaneparsons
la source
0
var calc = '<span style="display:none; margin:0 0 0 -999px">' + $('.move').text() + '</span>';
Yura
la source
0

Appelez getColumnWidth () pour obtenir le avec du texte. Cela fonctionne parfaitement bien.

someFile.css
.columnClass { 
    font-family: Verdana;
    font-size: 11px;
    font-weight: normal;
}


function getColumnWidth(columnClass,text) { 
    tempSpan = $('<span id="tempColumnWidth" class="'+columnClass+'" style="display:none">' + text + '</span>')
          .appendTo($('body'));
    columnWidth = tempSpan.width();
    tempSpan.remove();
return columnWidth;
}

Remarque: - Si vous voulez .css en ligne, transmettez les détails de la police uniquement avec style.

Arun Pratap Singh
la source
0

J'ai modifié le code de Nico pour qu'il réponde à mes besoins.

$.fn.textWidth = function(){
    var self = $(this),
        children = self.contents(),
        calculator = $('<span style="white-space:nowrap;" />'),
        width;

    children.wrap(calculator);
    width = children.parent().width(); // parent = the calculator wrapper
    children.unwrap();
    return width;
};

J'utilise .contents () car .children () ne renvoie pas les nœuds de texte dont j'avais besoin. J'ai également constaté que la largeur renvoyée était affectée par la largeur de la fenêtre qui provoquait un wrapping, donc j'utilise un espace blanc: nowrap; pour obtenir la largeur correcte quelle que soit la largeur de la fenêtre.

non_carbondated
la source
0
$.fn.textWidth = function(){
        var w = $('body').append($('<span stlye="display:none;" id="textWidth"/>')).find('#textWidth').html($(this).html()[0]).width();
        $('#textWidth').remove();
        console.log(w);
        return w;
    };

presque une seule doublure. Vous donne le avec du premier personnage

ceed
la source
0

Je ne pouvais faire fonctionner aucune des solutions répertoriées à 100%, j'ai donc proposé cet hybride , basé sur des idées de @chmurson (qui était à son tour basée sur @Okamera) et également de @philfreo:

(function ($)
{
    var calc;
    $.fn.textWidth = function ()
    {
        // Only create the dummy element once
        calc = calc || $('<span>').css('font', this.css('font')).css({'font-size': this.css('font-size'), display: 'none', 'white-space': 'nowrap' }).appendTo('body');
        var width = calc.html(this.html()).width();
        // Empty out the content until next time - not needed, but cleaner
        calc.empty();
        return width;
    };
})(jQuery);

Remarques:

  • thisà l'intérieur d'une méthode d'extension jQuery se trouve déjà un objet jQuery, donc pas besoin de tout le supplément $(this)que de nombreux exemples ont.
  • Il n'ajoute l'élément factice au corps qu'une seule fois et le réutilise.
  • Vous devez également préciser white-space: nowrap, juste pour vous assurer qu'il le mesure comme une seule ligne (et non un retour à la ligne basé sur un autre style de page).
  • Je n'ai pas pu faire fonctionner cela en utilisant font seul et devais également copier explicitement font-size. Je ne sais pas encore pourquoi (enquête toujours).
  • Cela ne prend pas en charge les champs de saisie de cette façon @philfreo.
Codage terminé
la source
0

Parfois, vous devez également mesurer la hauteur et non seulement le texte , mais également la largeur HTML . J'ai pris la réponse @philfreo et je l'ai rendue plus flexible et utile:

function htmlDimensions(html, font) {
  if (!htmlDimensions.dummyEl) {
    htmlDimensions.dummyEl = $('<div>').hide().appendTo(document.body);
  }
  htmlDimensions.dummyEl.html(html).css('font', font);
  return {
    height: htmlDimensions.dummyEl.height(),
    width: htmlDimensions.dummyEl.width()
  };
}
Daniel Kmak
la source
0

la largeur du texte peut être différente pour différents parents, par exemple si vous ajoutez un texte dans la balise h1, il sera plus large que div ou étiquette, donc ma solution comme celle-ci:

<h1 id="header1">

</h1>

alert(calcTextWidth("bir iki", $("#header1")));

function calcTextWidth(text, parentElem){
    var Elem = $("<label></label>").css("display", "none").text(text);
    parentElem.append(Elem);
  var width = Elem.width();
  Elem.remove();
    return width;
}
Saeed Taran
la source
0

J'ai eu des problèmes avec des solutions comme @ rune-kaagaard pour de grandes quantités de texte. J'ai découvert ceci:

$.fn.textWidth = function() {
	var width = 0;
	var calc = '<span style="display: block; width: 100%; overflow-y: scroll; white-space: nowrap;" class="textwidth"><span>' + $(this).html() + '</span></span>';
	$('body').append(calc);
	var last = $('body').find('span.textwidth:last');
	if (last) {
			var lastcontent = last.find('span');
			width = lastcontent.width();
			last.remove();
	}
	return width;
};

JSFiddle GitHub

peeto
la source
-1

je pense que tu devrais utiliser $('.calltoaction').val;

aussi, j'utiliserais id (#) au lieu d'une classe pour cela .. si vous avez plus d'une de ces classes, comment le gérerait-il?

Noam Smadja
la source
Oui, il y en a plus d'un dans le document. Pourquoi suggéreriez-vous id?
Dom