Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Динамическое изменение ширины в зависимости от содержимого (https://javascript.ru/forum/events/22703-dinamicheskoe-izmenenie-shiriny-v-zavisimosti-ot-soderzhimogo.html)

iNfantry 29.10.2011 17:36

Динамическое изменение ширины в зависимости от содержимого
 
Всем привет, вопрос очень простой и наверное избитый, но так и не смог найти внятного ответа.
Допустим есть элемент input type="text" и требуется менять его ширину динамически в зависимости от длины его value.
Как это сделать на jQuery? Или просто на js, не принципиально.

Aetae 29.10.2011 21:01

Утрируя:
<input type="text" size="1" onkeydown="size=value.length||1" onkeyup="onkeydown()" onkeypress="onkeydown()" onchange="onkeydown()">

iNfantry 29.10.2011 21:27

Сорри, наверно не до конца пояснил вопрос.
А проблема в том, что изменение size через жквери не меняет визуально ширину элемента, хотя в атрибут записывает. Не могу понять почему изменяя этот атрибут из жс внешне нифига не происходит.

ksa 29.10.2011 21:51

Цитата:

Сообщение от iNfantry
проблема в том, что изменение size через жквери не меняет визуально ширину элемента

Смотрел в Опере и ФФ - всё там работает...

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<!--
<link rel="stylesheet" type="text/css" href="tmp.css" />
-->
<style type="text/css">
</style>
<script type="text/javascript">
$(document).ready(function(){
	$('#test').bind('keyup keydown keypres select click',function(){
		var l=this.value.length;
		l=(l==0)? 1: l;
		$('#test').attr('size',l);
	});
});
</script>
</head>
<body>
<input id='test' size='1' type='text' />
</body>
</html>


Другое дело сайз не совсем совпадает с количеством элементов... :) Лучше подобрать моноширный шрифт и менять свойство цсс width.

Aetae 29.10.2011 22:03

Цитата:

Сообщение от ksa (Сообщение 133465)
l=(l==0)? 1: l;

Типа для наглядности? Имхо, перебор.)

ksa 29.10.2011 22:05

Цитата:

Сообщение от Aetae
Имхо, перебор.

В ФФ если size='0' - длинна поля становится "по умолчанию"... Т.е. принимает размер как

<input type='text' />

Aetae 29.10.2011 22:08

дык)
size=value.length||1

ksa 29.10.2011 22:11

Цитата:

Сообщение от Aetae
size=value.length||1

Учту...

Kolyaj 29.10.2011 22:11

Жестоко называть переменную l, а потом её ещё сравнивать с 1.

ksa 29.10.2011 22:14

Kolyaj, ну не такая уш это и жестокость... :D l ~ len.
Просто привык я к коротким именам переменных, команд и функций... У нас в Cache всё "понимается" по первой букве (максимум двум)...

Да и в редаторах цифры подсвечиваются не так как идентификаторы переменных...

Kolyaj 29.10.2011 22:15

В некоторых шрифтах l неотличима от 1.

ksa 29.10.2011 22:17

Цитата:

Сообщение от Kolyaj
В некоторых шрифтах l неотличима от 1.

Не ставь такие шрифты в редакторах... :D

Kolyaj 29.10.2011 22:22

Они при любом шрифте различимы только при внимательном рассмотрении.

Непонятно, почему нельзя назвать переменную length, или хотя бы len.

tenshi 30.10.2011 00:40

проще воспользоваться contenteditable

ksa 30.10.2011 10:55

Цитата:

Сообщение от Kolyaj
Непонятно, почему нельзя назвать переменную length, или хотя бы len.

Так я уже ответил на этот вопрос...
Цитата:

Сообщение от ksa
Просто привык я к коротким именам переменных, команд и функций...


iNfantry 31.10.2011 22:57

Сорри что пропал, выходные. ;)
Вобщем с size странная штука, если ниже каковото значения его делаю, например 0<size<5 то оно по умолчанию ставится. Но это пофиг, третестепенная проблема. Изменение css width работает, это я затупил где-то. Сейчас другие вопросы возникли.

1. Допустим есть колонка таблицы td, можно ли какото вычислить длину содержимого? Не длину самой колонки которая задана либо не задана, а именно длину содержимого. Но подозреваю что это невозможно, так?

2. Насчет колонки другой вопрос. Есть таблица, в ней несколько колонок. В какойто из центральных колонок находится див с текстом, по щелчку на тексте в див вместо текста вставляется инпут для редактирования. Проблема вот в чем - какой бы маленький инпут не вставлялся он вызывает скачок/растяжение колонки. При этом если вставлять в див еще один такой же див с таким же текстом то никакого скачка не происходит, всё четко. Я уже с этим инпутом намучался, и маргины ему задавал и прочие стили которые на ширину/высоту влияют, всё бестолку! Возможно ли его вставить чтоб не косячила колонка?? Еще раз чтоб понятно было поясню кодом:

есть
...
<tr><td>trololo1</td><td style="width:200px"><div id="123">text for edit</div></td><td>trololo2</td></tr>
...

простешим кодом на жкуери делаем

$('#123').html('<input type="text" value="text for edit" style="margin:0px; width:100px;" />')

И после этого происходит скачок, НЕСМОТРЯ НА ТО ЧТО длина инпута в 2 раза меньше длины колонки!

Aetae 01.11.2011 06:55

Лень вникать, попробуй:
table-layout fixed

tenshi 01.11.2011 09:30

иногда я чувствую себя призраком..

Aetae 01.11.2011 13:51

Цитата:

Сообщение от tenshi (Сообщение 133922)
иногда я чувствую себя призраком..

Вы хотите об этом поговорить?)

tenshi 02.11.2011 01:39

если честно, да..

trikadin 02.11.2011 02:14

Так пишите)

Ну или создайте тему. Обсудим.

ksa 02.11.2011 09:17

tenshi, тогда расскажи как это произошло в первый раз...

tenshi 02.11.2011 10:06

мне кажется меня не замечают.. все так заняты решением своих надуманных проблем, что не находят времени остановиться, оглядеться и увидеть более короткий путь.. меня угнетает, что какому-нибудь пиарящемуся гуру смотрят в рот, даже когда он несёт полную фигню, а мои аргументы молча игнорируются.. всё чаще я вижу непонимание со стороны окружающих и претензии вида "нахуа ты сделал так, а не как привык говнокодить я?"..

ksa 02.11.2011 10:21

Цитата:

Сообщение от tenshi
все так заняты решением своих надуманных проблем

Так это обычное дело для людей... Или ты супер человек и тебе это чуждо? :D
Цитата:

Сообщение от tenshi
меня угнетает, что какому-нибудь пиарящемуся гуру смотрят в рот

И ты решил теперь пропиариться самостоятельно? :)

tenshi 02.11.2011 10:52

приятного аппетита..

ksa 02.11.2011 10:53

Т.е. диалога опять не будет? :D

trikadin 02.11.2011 15:27

tenshi, мне кажется, бесполезно рассказывать вам о том, что вы не суперчеловек и не лишены человеческих слабостей.

Забейте на этих людей с их проблемами в таком случае - они же не ваши, в конце концов. Зачем вы грустите?

ksa 02.11.2011 15:37

Цитата:

Сообщение от trikadin
Зачем вы грустите?

Вспомнился анекдот...

- А что вы там в своей баптистской секте делаете?
- Так баб тискаем...

tenshi 03.11.2011 09:39

трудно забить на тех с кем приходится работать.. особенно на начальника..

Aetae 03.11.2011 09:46

Да, это печально.
Но тут ничего не поделаешь, увы, c'est la vie.
Разве что когда совсем надоест на текущей работе и будет невмоготу боле - притащить на работу тунца и отх*чить им коллег при первом же поводе.

trikadin 03.11.2011 13:43

Цитата:

Сообщение от tenshi
трудно забить на тех с кем приходится работать.. особенно на начальника..

А, ну если так, то это, конечно, да... Но я говорил про людей на форуме)

boor1 07.07.2017 15:52

******* по сабжу ******

Правильное (логичное) решение - через CSS:
нужно (как-то) заставить <INPUT> вести себя как <SPAN>

Свойство display=inline у обоих.
Нужно что-то ещё.

Или это невозможно задать параметрически для <INPUT>?

Malleys 08.07.2017 23:55

Текстовое поле является замещаемым элементом, размеры которого определяются внутри элемента. Следовательно размер элемента представляющего содержимое замещаемых элементов может иметь определённые ширину, высоту или соотношение сторон, если только не заданы конкретные размеры.

Давайте попробуем создать текстовое поле, которое занимало бы ширину равную ширине введённого текста...

<input value="London" placeholder="City">
<style>
	
	input {
		/* Для начала сбросим все стили */
		all: unset;
		/* Затем применим стили, чтобы увидеть какого размера теперь поле */
		border-bottom: 0.125em dashed deeppink;
		background-color: lightpink;
		padding: 0.5em;
		font: 2em Georgia, serif;
		display: inline-block;
		min-width: 1em; /* Обратите внимание, как применилось */
		max-width: 10em;
	}
	
</style>


Каким бы не был текст, ширина упорно не меняется, по причине указанной выше. Из-за этого min-width и max-width остаются по сути не применёнными. Но давайте попробуем эмулировать текстовое поле, используя атрибут contenteditable.

<span contenteditable placeholder="City">London</span>
<style>
	
	span[contenteditable] {
		/* Затем применим стили, чтобы увидеть какого размера теперь поле */
		border-bottom: 0.125em dashed deeppink;
		background-color: lightpink;
		padding: 0.5em;
		font: 2em Georgia, serif;
		display: inline-block;
		min-width: 1em; /* Обратите внимание, как применилось */
		max-width: 10em;
		/* стили специально для contenteditable */
		white-space: nowrap;
		overflow: hidden;
		cursor: text;
	}
	
	/* Браузеры для имитаций перевода строки используют div, p или br */
	/* Также могут применять инлайн-стили, для вставленных элементов */
	span[contenteditable] * {
		white-space: nowrap !important;
		font: unset !important;
		display: inline;
	}
	
	span[contenteditable] br {
		display: none;
	}
	
	/* Имитируем placeholder */
	span[contenteditable]:empty::before {
		content: attr(placeholder);
		opacity: 0.5;
	}
	
</style>


Теперь наше текстовое поле меняет размеры, как оно должно быть на самом деле
Правда здесь проблемы:
- Браузер вставляет элементы
- В поле можно перетащить изображения и другие элементы
- Это не элемент формы (нужно будет получить значение через textContent)

Плюсы:
+ Если предположить, что пользователь будет вводить или вставлять только текст, то ОК
+ Применяются min-width и max-width, т. е. ведёт себя не странно
+ textContent возвращает только текст
+ работает placeholder, доступен через клавиатуру

В черновике спецификаций работа над которой была прекращена, определялось свойство user-modify, которое позволяет редактировать содержимое элемента, если указано значение read-write. (https://www.w3.org/TR/2000/WD-css3-u...16#user-modify)

В принципе редактирование элемента может быть задано через стили. По сути...
Код:

[contenteditable] {
        user-modify: read-write;
}

Именно так оно и работает в некоторых браузерах, например в webkit используется свойство -webkit-user-modify. В webkit используется дополнительное значение read-write-plaintext-only, которое позволяет вставлять текст без оформления.

<span contenteditable placeholder="City">London</span>
<style>
	
	span[contenteditable] {
		/* Затем применим стили, чтобы увидеть какого размера теперь поле */
		border-bottom: 0.125em dashed deeppink;
		background-color: lightpink;
		padding: 0.5em;
		font: 2em Georgia, serif;
		display: inline-grid;
		display: inline-flex;
		min-width: 1em; /* Обратите внимание, как применилось */
		max-width: 10em;
		/* стили специально для contenteditable */
		-webkit-user-modify: read-write-plaintext-only;
		cursor: text;
	}
	
	/* Имитируем placeholder */
	span[contenteditable]:empty::before {
		content: attr(placeholder);
		opacity: 0.5;
	}
	
</style>


Это всё не работает как элемент формы, но можно взять элемент формы и сделать программно вокруг него обёртку, которая позволяла бы отслеживать его размеры (при помощи стилей, обёртка скриптом).

<input value="London" placeholder="City">
<style>
	
	input, x-input {
		/* Затем применим стили, чтобы увидеть какого размера теперь поле */
		border-bottom: 0.125em dashed deeppink;
		background-color: lightpink;
		padding: 0.5em;
		font: 2em Georgia, serif;
		display: inline-block;
		min-width: 1em; /* Обратите внимание, как применилось */
		max-width: 10em;
	}
	
</style>
<script>
for(let element of document.querySelectorAll("input")) {
	let host = document.createElement("x-input")
	let parent = host.attachShadow({ mode: "open" });
	let style = document.createElement("style");
	let input = element.cloneNode(true);
	input.placeholder = element.getAttribute("placeholder");
	let field = document.createElement("span");
	
	style.textContent = `
		:host {
			position: relative;
			overflow: hidden;
		}

		input {
			all: inherit;
			margin: 0;
			border: 0;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			width: 100%;
			height: 100%;
			opacity: 1;
			position: absolute;
			box-sizing: border-box;
			max-width: initial;
			max-height: initial;
			min-width: initial;
			min-height: initial;
		}

		span {
			visibility: hidden;
		}
	`;
	
	element.parentNode.insertBefore(host, element.nextSibling);
	
	parent.appendChild(style);
	parent.appendChild(input);
	parent.appendChild(field);
	
	let inputHandler = () => {
		field.textContent = (input.value || input.placeholder).replace(/\s/g, "\xa0");
		element.value = input.value;
	};
	
	input.addEventListener("input", inputHandler);
	inputHandler();
	
	element.type = "hidden";
}
</script>


И ещё один способ, от Ли Веру. Тоже отслеживает размеры (при помощи скрипта).

<input value="London" placeholder="City">
<style>
	
	input {
		all: unset;
		/* Затем применим стили, чтобы увидеть какого размера теперь поле */
		border-bottom: 0.125em dashed deeppink;
		background-color: lightpink;
		padding: 0.5em;
		display: inline-block;
		font: 2em Georgia, serif;
		min-width: 1em; /* Обратите внимание, как применилось */
		max-width: 10em;
	}
	
</style>
<script src="https://leaverou.github.io/stretchy/stretchy.js"></script>


Кто знает, как ещё проще?

Определение замещаемого элемента(https://www.w3.org/TR/CSS21/conform.html, https://www.w3.org/TR/2014/REC-html5...laced-elements)

Маэстро 24.07.2017 18:17

Цитата:

Сообщение от Malleys (Сообщение 457990)
Кто знает, как ещё проще?

Старая тема (6 лет назад подняли). Но если кому-то нужно поделюсь своим вариантом. Фишка в создании "теневого спана" - копии инпута. Браузер сам вычисляет ширину элемента в зависимости от названия шрифта, его размера и длины текстовой строки. Нам надо её просто взять.
Свойства стиля в <span> и <input> должны полностью совпадать (некоторые браузеры не наследуют в input font-family по inherit).
<html>
<style>
.inp {font-family:calibri,arial,sans-serif; font-size:1em; padding:.2px; background-color:#DDDDFF; border:1px solid #F00; min-width:1em}
</style>
<body>
<script>
function rsz()
{
setTimeout(function(){
 var inp = document.getElementById('inp1');
 var spa = document.getElementById('inp1copy');
 ///spa.innerText = inp.value; // так не учитывает пробелы
 spa.innerText = inp.value.replace(/\s/ig, String.fromCharCode(160));
 inp.style.width=spa.offsetWidth + 20; // 20px чтобы инпут не дергался при вводе нового символа
                     },0);
};

</script>

<input id="inp1" class="inp" style="width:10px" type="input" value="" onkeydown="rsz()" onpaste="rsz()" oncut="rsz()">
<span id="inp1copy" class="inp" style="position:absolute; left:-30000px; top:0px"> </span>
</body>
</html>

laimas 24.07.2017 19:01

Цитата:

Сообщение от Маэстро
/\s/i

А пробел может иметь верхний и нижний регистры? :)

Маэстро 24.07.2017 19:06

Цитата:

Сообщение от laimas (Сообщение 459449)
А пробел может иметь верхний и нижний регистры? :)

ну погорячился.. писал по памяти из проекта двухлетней давности..
собственно, для понимания идеи это не важно. хотя Ваше замечание об аккуратности оформления кода учту

laimas 24.07.2017 19:23

Цитата:

Сообщение от Маэстро
замечание об аккуратности

Тут более правильно говорить о нагрузке, так не "учитывать регистр" означает дополнительное действие над символом. Или например, если говорить о более мощном REGEXP, чего нет в JS, но так, к слову, то для нахождения английских символов в юникод строке также не обязательно указывать модификатор u, так как этот набор в строке будет все равно однобайтовым.

Маэстро 24.07.2017 19:28

Цитата:

Сообщение от laimas (Сообщение 459454)
Тут более правильно говорить о нагрузке

К нагрузке я тоже всегда отношусь очень щепетильно. Но это не тот случай. После нажатия на клавишу (даже в режиме автоповтора) даже самый слабый процессор успеет сделать замену символа. Речь не идет о 100000 операциях в цикле. 100 ms между нажатиями клавиш ему хватит с головой. Это просто "опечатка", не ведущая ни к каким печальным последствиям, тем более в учебном примере.

laimas 24.07.2017 19:38

Я не о ядрах процессора говорю, а о том, что разбор будет производится с лишними операциями, а зачем? Можно ссылаться на то, что выросли возможности процессоров, но зачем же лишнее делать. Все лишнее зря кушает энергию, которая для моб. устройств является чувствительной. :)


Часовой пояс GMT +3, время: 01:33.