Я пытаюсь рассчитать ширину текста с помощью jQuery. Не знаю, что, но я определенно делаю что-то не так.
Итак, вот код:
var c = $('.calltoaction');
var cTxt = c.text();
var cWidth = cTxt.outerWidth();
c.css('width' , cWidth);
Я пытаюсь рассчитать ширину текста с помощью jQuery. Не знаю, что, но я определенно делаю что-то не так.
Итак, вот код:
var c = $('.calltoaction');
var cTxt = c.text();
var cWidth = cTxt.outerWidth();
c.css('width' , cWidth);
Ответы:
У меня это сработало лучше:
$.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;
};
'</span>', хотя это, похоже, не имеет значения (работает с ней или без нее на FF9).
Вот функция, которая лучше, чем другие опубликованные, потому что
<input>, <span>или "string".Демо: 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();
};
$.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;
};
По сути, улучшение по сравнению с Рунами, которое не .htmlтак легко использовать
/перед закрывающей скобкой <span>тега:calculator = $('<span style="display: inline-block;" />'),
Эти textWidthфункции , предусмотренные в ответах , и которые принимают в stringкачестве аргумента , не будет составлять начальную и конечные пробела (те , которые не отображаются в контейнере фиктивного). Кроме того, они не будут работать, если текст содержит какую-либо разметку html (подстрока <br>не будет производить никакого вывода и вернет длину одного пробела).
Это проблема только для textWidthфункций, которые принимают a string, потому что, если элемент DOM задан и .html()вызывается элементом, то, вероятно, нет необходимости исправлять это для такого варианта использования.
Но если, например, вы вычисляете ширину текста для динамического изменения ширины текстового inputэлемента в зависимости от типов пользователей (мой текущий вариант использования), вы, вероятно, захотите заменить начальные и конечные пробелы на и закодировать строку в html.
Я использовал решение philfreo, поэтому вот его версия, которая это исправляет (с комментариями к дополнениям):
$.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, " "); //replace trailing and leading spaces
$.fn.textWidth.fakeEl.html(htmlText).css('font', font || this.css('font'));
return $.fn.textWidth.fakeEl.width();
};
font-size. Пришлось добавить, css('font-size'), this.css('font-size'))чтобы он заработал. Любые идеи, почему fontодно не копирует это значение?
.cssметод, но я вижу, что мои скобки неправильные. Должно быть css('font-size', this.css('font-size')).
Функции ширины jQuery могут быть немного сомнительными при попытке определить ширину текста из-за несовместимых блочных моделей. Верным способом было бы вставить div внутри вашего элемента, чтобы определить фактическую ширину текста:
$.fn.textWidth = function(){
var sensor = $('<div />').css({margin: 0, padding: 0});
$(this).append(sensor);
var width = sensor.width();
sensor.remove();
return width;
};
Чтобы использовать этот мини-плагин, просто:
$('.calltoaction').textWidth();
spanвы просто получите ноль. Пробовал это решение на H2, где у родительских элементов скрыто переполнение, и я получаю только усеченную длину текста. Возможно, объяснение того, как это должно работать , поможет улучшить его работу?
Я обнаружил, что это решение работает хорошо, и оно наследует исходный шрифт перед изменением размера:
$.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;
}
org.css("font-weight"). Также я бы сказал, что эта if(!text)часть не интуитивно понятна. Если я использую, например, jQuery("#someContainer").textWidth("Lorem ipsum")я хотел бы знать ширину текста «Lorem ipsum» при применении в этом конкретном контейнере.
Ни Rune, ни Brain у меня не работали в том случае, если элемент, содержащий текст, имел фиксированную ширину. Я сделал что-то похожее на Окамеру. Он использует меньше селекторов.
РЕДАКТИРОВАТЬ: это, вероятно, не сработает для элементов, которые используют относительные font-size, поскольку следующий код вставляет htmlCalcэлемент в, bodyтаким образом, теряет информацию о родительских отношениях.
$.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;
};
thisуже является объектом jQuery, поэтому $(this)он избыточен.
Если вы пытаетесь сделать это с текстом в поле выбора или если эти два не работают, попробуйте это вместо этого:
$.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;
};
или
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;
};
если вы хотите сначала схватить текст
дело в том, что вы делаете неправильно, что вы вызываете метод cTxt, который представляет собой простую строку, а не объект jQuery. cTxt - это действительно содержащийся текст.
Небольшое изменение для Нико, поскольку .children () вернет пустой набор, если мы ссылаемся на текстовый элемент, такой как h1 или p . Поэтому мы будем использовать .contents () вместо этого и использовать this вместо $ (this), поскольку мы создаем метод для объекта 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;
};
после двух дней погони за призраком, пытаясь понять, почему ширина текста была неправильной, я понял, что это было из-за пробелов в текстовой строке, которые остановили вычисление ширины.
Итак, еще один совет - проверить, не вызывают ли пробелы проблемы. использовать
неразрывное пространство и посмотрите, исправит ли это его.
другие функции, которые люди предлагали, тоже работают хорошо, но проблемы вызывают пробелы.
white-space: nowrapвстроенный CSS, чтобы избежать этого.
Если вы пытаетесь определить ширину комбинации текстовых узлов и элементов внутри данного элемента, вам необходимо обернуть все содержимое с помощью wrapInner () , вычислить ширину, а затем развернуть содержимое.
* Примечание. Вам также потребуется расширить jQuery, чтобы добавить функцию unwrapInner (), поскольку она не предоставляется по умолчанию.
$.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;
}
});
Расширение ответа @ philfreo:
Я добавил возможность проверки text-transform, так как такие вещи text-transform: uppercaseобычно делают текст шире.
$.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();
};
Вызовите getColumnWidth (), чтобы получить содержание текста. Это прекрасно работает.
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;
}
Примечание: - Если вы хотите, чтобы встроенный .css передавал детали шрифта только в стиле.
Я изменил код Нико для своих нужд.
$.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;
};
Я использую .contents (), поскольку .children () не возвращает текстовые узлы, которые мне нужны. Я также обнаружил, что на возвращаемую ширину влияет ширина области просмотра, которая вызвала перенос, поэтому я использую white-space: nowrap; чтобы получить правильную ширину независимо от ширины области просмотра.
Я не смог заставить ни одно из перечисленных решений работать на 100%, поэтому придумал этот гибрид , основанный на идеях от @chmurson (который, в свою очередь, был основан на @Okamera), а также от @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);
this внутри метода расширения jQuery уже есть объект jQuery, поэтому нет необходимости во всех дополнительных $(this) которые есть во многих примерах.white-space: nowrap, чтобы убедиться, что он измеряется как одна строка (а не перенос строки на основе других стилей страницы).fontодин, и мне также пришлось явно копировать font-size. Пока не уверен, почему (все еще исследую).@philfreo.Иногда нужно дополнительно измерить высоту и не только текст , но и ширину HTML . Я взял ответ @philfreo и сделал его более гибким и полезным:
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()
};
}
ширина текста может быть разной для разных родителей, например, если вы добавляете текст в тег h1, он будет шире, чем div или label, поэтому мое решение вроде этого:
<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;
}
У меня были проблемы с решениями типа @ rune-kaagaard для больших объемов текста. Я обнаружил это:
$.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;
};
я думаю, тебе стоит использовать $('.calltoaction').val;
Кроме того, я бы использовал id (#) вместо класса для этого ... если у вас есть несколько таких классов, как бы он с этим справился?