Menghitung lebar teks

101

Saya mencoba menghitung lebar teks menggunakan jQuery. Saya tidak yakin apa, tapi saya pasti melakukan sesuatu yang salah.

Jadi, inilah kodenya:

var c = $('.calltoaction');

var cTxt = c.text();

var cWidth =  cTxt.outerWidth();

c.css('width' , cWidth);
Dom
sumber
Jadi, dengan cara apa kode itu tidak berfungsi? Apa yang perlu dilakukannya secara berbeda?
Sixten Otto

Jawaban:

142

Ini bekerja lebih baik untuk saya:

$.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
sumber
4
+1 - ini benar-benar mengukur teks, bukan hanya elemen blok yang mengandung seperti solusi brainreavis.
Ben
Licin. +1. Sepertinya Anda kehilangan titik koma pada baris ketiga setelahnya '</span>', meskipun tampaknya tidak ada bedanya (bekerja dengan atau tanpa titik koma di FF9).
shmeep
21
Berhati-hatilah dengan ini ... metode ini akan melepaskan setiap kejadian pada elemen anak.
Brianreavis
Saya telah mencoba menggunakan fungsi ini dalam beberapa cara, tetapi tetap mengembalikan nol. Bisakah seseorang memposting sintaks tentang bagaimana fungsi ini sebenarnya digunakan? Apakah saya menjalankan fungsi .textWidth () pada objek jQuery? Apakah saya meneruskan teks ke fungsi ini? Apakah saya menjalankan fungsi sebagai fungsi jQuery (yaitu $ .textWidth (jqObject)? Karena tidak ada opsi tersebut yang berfungsi. Terima kasih ...
moosefetcher
2
@moosefetcher Anda akan melakukan $ (selector) .textWidth (); Lihat di sini learn.jquery.com/plugins/basic-plugin-creation/…
uesports135
89

Berikut adalah fungsi yang lebih baik daripada yang diposting lainnya karena

  1. itu lebih pendek
  2. bekerja ketika melewati sebuah <input>, <span>, atau "string".
  3. lebih cepat untuk penggunaan yang sering karena menggunakan kembali elemen DOM yang ada.

Demo: 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.dll
sumber
1
Wow! Keangkeran murni!
Michel Triana
3
Solusi hebat, harus diterima jawaban, saya pikir! Terima kasih, sobat!
Ilia Rostovtsev
Fantastico! Sederhana dan bersih.
Carey Estes
Meskipun bagus, ini tidak menangani ruang. Lihat jawaban @ edsioufi untuk peningkatan solusi ini.
Badgerspot
Jika ada teks tersembunyi di dalam elemen, maka lebar Anda akan miring. Untuk menjelaskan hal ini, pastikan untuk menghapus node tersembunyi sebelum menghitung lebar teks. Untuk menghapus node tersembunyi dengan aman, Anda mungkin harus membuat klon terlebih dahulu dan melakukan penghapusan di sana.
thdoan
36

Solusi saya

$.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;
};

Pada dasarnya peningkatan dari Rune, yang tidak digunakan .htmldengan mudah

bevacqua.dll
sumber
Oleh Ajarn Gerhard yang memposting ini sebagai jawaban: Ini tidak berfungsi di IE8 karena Anda melewatkan /sebelum tanda kurung tutup dari <span>tag:calculator = $('<span style="display: inline-block;" />'),
Petr R.
1
Ini tampaknya mengembalikan nol jika ada elemen anak di bawah elemen yang Anda ukur. Bisakah itu dibuat untuk bekerja tanpa elemen anak? Lihat jsfiddle.net/h22tj/41
Casper
+1 - Saya tidak pernah tahu ada bungkusan (), yang menyebabkan saya sangat sedih.
Orwellophile
Itu selalu mengembalikan nol di Chrome.
emeraldhieu
12

The textWidthfungsi yang disediakan dalam jawaban dan yang menerima stringsebagai argumen tidak akan memperhitungkan terkemuka dan trailing spasi putih (yang tidak diberikan dalam wadah dummy). Juga, mereka tidak akan bekerja jika teks berisi markup html apa pun (sub-string <br>tidak akan menghasilkan keluaran apa pun dan &nbsp;akan mengembalikan panjang satu spasi).

Ini hanya masalah untuk textWidthfungsi yang menerima a string, karena jika elemen DOM diberikan, dan .html()dipanggil ke elemen tersebut, mungkin tidak perlu memperbaikinya untuk kasus penggunaan seperti itu.

Tetapi jika, misalnya, Anda menghitung lebar teks untuk secara dinamis mengubah lebar inputelemen teks saat pengguna mengetik (kasus penggunaan saya saat ini), Anda mungkin ingin mengganti spasi di depan dan di belakang dengan &nbsp;dan menyandikan string ke html.

Saya menggunakan solusi philfreo jadi berikut adalah versi yang memperbaiki ini (dengan komentar tentang tambahan):

$.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
sumber
Terima kasih. Jawaban Anda sangat berharga.
Vishal
1
Anehnya, ketika saya mencoba yang ini, itu tidak menyalin file font-size. Saya harus menambahkannya css('font-size'), this.css('font-size'))agar berfungsi. Ada ide mengapa fontsaja tidak menyalin nilai itu?
Pergi Coding
@GoneCoding Di mana Anda menambahkan ekstra tersebut?
webmagnets
@webmagnets: Tempat yang sama dengan .cssmetode yang ada , tetapi saya melihat tanda kurung saya salah. Seharusnya css('font-size', this.css('font-size')).
Pergi Coding
11

Fungsi lebar jQuery bisa sedikit teduh saat mencoba menentukan lebar teks karena model kotak yang tidak konsisten. Cara yang pasti adalah dengan memasukkan div di dalam elemen Anda untuk menentukan lebar teks yang sebenarnya:

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

Untuk menggunakan plugin mini ini, cukup:

$('.calltoaction').textWidth();
brianreavis.dll
sumber
1
Bukankah ini memberi Anda lebar blok daripada teks?
Josh Rickard
-1 Ini tampaknya mengukur lebar kotak daripada lebar teks.
Nathan Arthur
1
Bukankah hanya menggunakan span daripada div memperbaiki masalah lebar? Jika demikian, maka fungsi ini sedikit lebih baik daripada jawaban yang diterima.
Josh
@ Josh: Jika Anda menggantinya dengan spanAnda hanya mendapatkan nol. Mencoba solusi ini pada H2, di mana elemen induk telah melimpah tersembunyi, dan saya hanya mendapatkan panjang teks yang terpotong. Mungkin penjelasan tentang bagaimana ini seharusnya bekerja akan membantu membuatnya bekerja lebih baik?
Gone Coding
8

Saya menemukan solusi ini berfungsi dengan baik dan mewarisi font asal sebelum mengukur:

$.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
sumber
1
Saya akhirnya menggunakan ini, tetapi ditambahkan org.css("font-weight"). Juga, saya akan mengatakan bahwa if(!text)bagian itu tidak intuitif. Jika saya menggunakan misalnya, jQuery("#someContainer").textWidth("Lorem ipsum")saya ingin mengetahui lebar teks "Lorem ipsum" ketika diterapkan dalam wadah tertentu.
Sleavely
8

Baik Rune maupun Brain tidak bekerja untukku jika elemen yang menahan teks memiliki lebar tetap. Saya melakukan sesuatu yang mirip dengan Okamera. Ini menggunakan lebih sedikit penyeleksi.

EDIT: Ini mungkin tidak akan berfungsi untuk elemen yang menggunakan relatif font-size, karena kode berikut memasukkan htmlCalcelemen ke dalam bodysehingga kehilangan informasi tentang relasi orang tua.

$.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.dll
sumber
Ini adalah solusi terbaik bagi saya dengan dukungan IE8 dan tidak akan merusak ikatan apa pun ke elemen dalam prosesnya! Terima kasih.
ouija
catatan: Dalam metode ekstensi jQuery, thissudah menjadi objek jQuery jadi $(this)redundan.
Gone Coding
Ini tidak berhasil bagi saya, karena lebar yang dihitung terlalu kecil. Jawaban yang diterima bekerja dengan benar
PandaWood
5

Jika Anda mencoba melakukan ini dengan teks di kotak pilih atau jika keduanya tidak berfungsi, coba yang ini:

$.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;
};

atau

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;
};

jika Anda ingin mengambil teks terlebih dahulu

okamera
sumber
4

masalahnya, Anda melakukan kesalahan, bahwa Anda memanggil metode pada cTxt, yang merupakan string sederhana dan bukan objek jQuery. cTxt sebenarnya adalah teks yang terkandung.

Juraj Blahunka
sumber
2

Sedikit perubahan ke Nico's, karena .children () akan mengembalikan himpunan kosong jika kita mereferensikan elemen teks seperti h1 atau p . Jadi kita akan menggunakan .contents () sebagai gantinya, dan menggunakan ini sebagai ganti $ (this) karena kita membuat metode pada objek 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 desainer
sumber
1

Setelah mengejar hantu selama dua hari, mencoba mencari tahu mengapa lebar teks salah, saya menyadari itu karena spasi putih dalam string teks yang akan menghentikan perhitungan lebar.

jadi, tip lainnya adalah memeriksa apakah spasi putih menyebabkan masalah. menggunakan

&nbsp;

ruang non-breaking dan lihat apakah itu memperbaikinya.

fungsi lain yang disarankan orang bekerja dengan baik juga, tetapi ruang putih yang menyebabkan masalah.

zonabi
sumber
Cukup tambahkan sementara white-space: nowrapke inline CSS untuk menghindari ini.
Gone Coding
1

Jika Anda mencoba menentukan lebar campuran node teks dan elemen di dalam elemen tertentu, Anda perlu membungkus semua konten dengan wrapInner () , menghitung lebarnya, lalu membuka isinya.

* Catatan: Anda juga perlu memperluas jQuery untuk menambahkan fungsi unwrapInner () karena tidak disediakan secara default.

$.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;
  }
});
trip41
sumber
1 untuk .wrapInner. Seperti yang mungkin Anda ketahui, berurusan dengan elemen teks murni di jQuery adalah neraka. Jika ada metode jQuery lain yang dapat diterapkan, beri tahu saya. Saya harus menggunakan .get (0) .children dan itu tidak cantik.
Orwellophile
1

Memperluas jawaban @ philfreo:

Saya telah menambahkan kemampuan untuk memeriksa text-transform, karena hal-hal seperti text-transform: uppercasebiasanya cenderung membuat teks lebih lebar.

$.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
sumber
0
var calc = '<span style="display:none; margin:0 0 0 -999px">' + $('.move').text() + '</span>';
yura
sumber
0

Panggil getColumnWidth () untuk mendapatkan teks. Ini bekerja dengan baik.

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;
}

Catatan: - Jika Anda ingin inline .css teruskan detail font dalam gaya saja.

Arun Pratap Singh
sumber
0

Saya memodifikasi kode Nico agar sesuai dengan kebutuhan saya.

$.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;
};

Saya menggunakan .contents () karena .children () tidak mengembalikan node teks yang saya butuhkan. Saya juga menemukan bahwa lebar yang dikembalikan dipengaruhi oleh lebar viewport yang menyebabkan pembungkusan jadi saya menggunakan white-space: nowrap; untuk mendapatkan lebar yang benar terlepas dari lebar viewport.

non_carbondated
sumber
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;
    };

hampir satu kapal. Memberi Anda dengan karakter pertama

ceed
sumber
0

Saya tidak bisa mendapatkan solusi apa pun yang terdaftar untuk bekerja 100%, jadi buatlah hibrida ini , berdasarkan ide dari @chmurson (yang pada gilirannya didasarkan pada @Okamera) dan juga dari @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);

Catatan:

  • thisdi dalam metode ekstensi jQuery sudah menjadi objek jQuery, jadi tidak perlu semua tambahan yang $(this)dimiliki banyak contoh.
  • Itu hanya menambahkan elemen boneka ke tubuh satu kali, dan menggunakannya kembali.
  • Anda juga harus menentukan white-space: nowrap, hanya untuk memastikan bahwa itu mengukurnya sebagai satu baris (dan bukan garis pembungkus berdasarkan gaya halaman lain).
  • Saya tidak bisa mendapatkan ini untuk bekerja menggunakan fontsendiri dan harus menyalin secara eksplisit font-sizejuga. Belum yakin mengapa (masih menyelidiki).
  • Ini tidak mendukung kolom input seperti @philfreoitu.
Hilang Coding
sumber
0

Terkadang Anda juga perlu mengukur tinggi tambahan dan tidak hanya teks , tetapi juga lebar HTML . Saya mengambil jawaban @philfreo dan membuatnya lebih fleksibel dan berguna:

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
sumber
0

lebar teks bisa berbeda untuk orang tua yang berbeda, misalnya jika Anda menambahkan teks ke dalam tag h1 akan lebih lebar dari div atau label, jadi solusi saya seperti ini:

<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
sumber
0

Saya mengalami masalah dengan solusi seperti @ rune-kaagaard untuk teks dalam jumlah besar. Saya menemukan ini:

$.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
sumber
-1

saya pikir Anda harus menggunakan $('.calltoaction').val;

juga, saya akan menggunakan id (#) daripada kelas untuk itu .. jika u memiliki lebih dari satu kelas yang bagaimana cara mengatasinya?

Noam Smadja
sumber
Ya, ada lebih dari satu di dokumen. Mengapa Anda menyarankan id?
Dom