Подтвердить что ты не робот

Контент-доступный однострочный ввод

Для приложения, которое мы разрабатываем в компании, где я работаю, нам нужен вход, который поддерживает вставку смайликов внутри нашего веб-приложения на основе JS. В настоящее время мы используем ввод с яркими кодами смайликов (например, ':-)') и хотели бы переключиться на вставку фактических графических изображений.

Наш первоначальный план состоял в использовании contenteditable <div>. Мы используем прослушиватели для события вставки, а также различные взаимодействия с клавишами/мышью, чтобы гарантировать, что нежелательная разметка не попадет в контентную информацию (мы выкладываем текст из своих тегов контейнера и оставляем только теги изображений, которые мы вставили сами).

Однако проблема прямо сейчас заключается в том, что div изменяет размер, если вы разместите достаточно контента (т.е. увеличите его высоту). Мы не хотим, чтобы это произошло, и неприемлемо, чтобы текст был просто скрыт (т.е. простой overflow: hidden). Итак:

Есть ли способ сделать contenteditable div вести себя как однострочный ввод?

Я бы хотел, чтобы это было лучше, если бы было относительно простое свойство attribute/css, которое я пропустил, что будет делать то, что я хочу, но при необходимости также будут предложены предложения CSS + JS.

4b9b3361

Ответ 1

[contenteditable="true"].single-line {
    white-space: nowrap;
    width:200px;
    overflow: hidden;
} 
[contenteditable="true"].single-line br {
    display:none;

}
[contenteditable="true"].single-line * {
    display:inline;
    white-space:nowrap;
}
<div contenteditable="true" class="single-line">
    This should work.
</div>​

Ответ 2

Я думаю, что вы ищете contenteditable div только с одной строкой текста, которая прокручивается по горизонтали, когда она переполняет div. Это должно сделать трюк: http://jsfiddle.net/F6C9T/1

div {
    font-family: Arial;
    font-size: 18px;
    min-height: 40px;
    width: 300px;
    border: 1px solid red;
    overflow: hidden;
    white-space: nowrap;
}
<div contenteditable>
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
</div>

Ответ 3

Здесь относительно простое решение, которое использует контентное входное событие для сканирования dom и отфильтровывает различные варианты новых строк (так что оно должно быть надежным против копирования/вставки, перетаскивания вниз, нажатия на клавиатуре и т.д.), Он конденсирует несколько TextNodes в отдельные TextNodes, переводит новые строки из TextNodes, убивает BR и помещает "display: inline" в любой другой элемент, который он затрагивает. Протестировано в Chrome, без каких-либо гарантий.

var editable = $('#editable')

editable.on('input', function() {
  return filter_newlines(editable);
});


function filter_newlines(div) {
    var node, prev, _i, _len, _ref, _results;
    prev = null;
    _ref = div.contents();
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        node = _ref[_i];
        if (node.nodeType === 3) {
            node.nodeValue = node.nodeValue.replace('\n', '');
            if (prev) {
                node.nodeValue = prev.nodeValue + node.nodeValue;
                $(prev).remove();
            }
            _results.push(prev = node);
        } else if (node.tagName.toLowerCase() === 'br') {
            _results.push($(node).remove());
        } else {
            $(node).css('display', 'inline');
            filter_newlines($(node));
            _results.push(prev = null);
        }
    }
    return _results;
}
#editable {
    width: 200px;
    height: 20px;
    border: 1px solid black;
}
<div id="editable" contenteditable="true"></div>

Ответ 4

Итак, для потомков: самое простое решение - заставить менеджера вашего продукта изменять требования, чтобы вы могли выполнять многострочное редактирование. Именно это и произошло в нашем случае.

Однако, до того, как это произошло, я закончил работу над созданием вручную переносимого однострочного редактора richtext. Я завернул его в плагин jQuery в конце. У меня нет времени, чтобы закончить его (возможно, в IE есть ошибки, Firefox работает лучше всего, и Chrome работает очень хорошо - комментарии скудны, а иногда и не очень ясны). Он использует части Rangy library (извлечен, потому что я не хотел полагаться на полную библиотеку), чтобы получить позиции экрана для выбора, чтобы проверьте положение мыши относительно выбора (чтобы вы могли перетаскивать выделение и перемещать окно).

Грубо, он работает, используя 3 элемента. Внешний div (то, что вы называете плагином), которое получает переполнение: скрытое, а затем 2 уровня вложенности внутри него. Первый уровень абсолютно позиционируется, второй уровень является актуальным. Это разделение необходимо, потому что в противном случае некоторые браузеры предоставят контент-ориентированные абсолютно позиционированные элементы grippies, чтобы пользователь мог перемещать его вокруг...

В любом случае, существует целая куча кода для перемещения абсолютно позиционированного элемента внутри верхнего элемента, таким образом, перемещая фактическое содержимое. Сам контент-контент имеет white-space nowrap и т.д., Чтобы заставить его оставаться одной строкой.

В плагине также есть код, который удаляет все, что не является изображением (например, br, таблицы и т.д.) из любого текста, который вставлен/перетащен в поле. Вам нужны некоторые части этого (например, brs, абзац/нормализация абзацев и т.д.), Но, возможно, вы обычно захотите сохранить ссылки, em, strong и/или другое форматирование.

Источник: https://gist.github.com/1161922

Ответ 5

Проверьте этот ответ, который я только что опубликовал. Это должно помочь вам:

Как создать одностраничную вкладку content3dable HTML5, которая прослушивает Enter и Esc

Вот разметка HTML:

<span contenteditable="false"></span>

Вот jQuery/javascript:

$(document).ready(function() {
    $('[contenteditable]').dblclick(function() {
        $(this).attr('contenteditable', 'true');
        clearSelection();
        $(this).trigger('focus');
    });

    $('[contenteditable]').live('focus', function() {
        before = $(this).text();
        if($(this).attr('contenteditable') == "true") { $(this).css('border', '1px solid #ffd646'); }
    //}).live('paste', function() {
    }).live('blur', function() {
        $(this).attr('contenteditable', 'false');
        $(this).css('border', '1px solid #fafafa');
        $(this).text($(this).text().replace(/(\r\n|\n|\r)/gm,""));

        if (before != $(this).text()) { $(this).trigger('change'); }
    }).live('keyup', function(event) {
        // ESC=27, Enter=13
        if (event.which == 27) {
            $(this).text(before);
            $(this).trigger('blur');
        } else if (event.which == 13) {
            $(this).trigger('blur');
        }
    });

    $('[contenteditable]').live('change', function() {
        var $thisText = $(this).text();
        //Do something with the new value.
    });
});

function clearSelection() {
    if ( document.selection ) {
        document.selection.empty();
    } else if ( window.getSelection ) {
        window.getSelection().removeAllRanges();
    }
}

Надеюсь, это поможет кому-то!!!

Ответ 6

Если вам нужен другой способ его решения, кроме изменения требований, с небольшим display:table вполне возможно =)

.container1 {
    height:20px;
    width:273px; 
    overflow:hidden;
    border:1px solid green;
}
.container2 {
    display:table;
}
.textarea {
    width:273px;
    font-size: 18px;
    font-weight: normal;
    line-height: 18px;
    outline: none;
    display: table-cell;
    position: relative;
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    user-select: text;
    word-wrap: break-word;    
    overflow:hidden;
}
<div class="container1">
    <div class="container2">
        <div contenteditable="true" class="textarea"></div>
    </div>
</div>

Ответ 7

Вы можете заменить этот div текстовым вводом (после вызова события onclick).
Я использовал что-то похожее на этот плагин, и он работал нормально.

Ответ 8

Другие ответы неверны и содержат мало ошибок (на 2019-05-07). Другие решения предлагают использовать "white-space: nowrap" (предотвращает перенос на другую строку) + "overflow: hidden" (предотвращает выход длинного текста за пределы поля) + скрытие <br> и другое.

Первая ошибка в том, что решения "переполнение: скрыто" также предотвращает прокрутку текста. Пользователь не сможет прокрутить текст:

  • Нажатие средней кнопки мыши
  • Выделение текста и перемещение указателя мыши влево или вправо
  • Использование горизонтальной прокрутки мыши (когда у пользователя есть такая вещь)

Единственный способ, которым он может прокручивать это использование стрелок на клавиатуре.

Вы можете решить эту проблему, используя одновременно "overflow: hidden" и "overflow: auto" (или "scroll"). Вы должны создать родительский div с "overflow: hidden", чтобы скрыть содержимое, которое пользователь не должен видеть. Этот элемент должен иметь входные границы и другой дизайн. И вы должны создать дочерний div с атрибутами "overflow-x: auto" и "contenteditable". Этот элемент будет иметь полосу прокрутки, поэтому пользователь может прокручивать ее без каких-либо ограничений, и он не увидит эту полосу прокрутки из-за скрытия переполнения в родительском элементе.

Пример решения:

document.querySelectorAll('.CETextInput').forEach(el => {
	//Focusing on child element after clicking parent. We need it because parent element has bigger width than child.
	el.parentNode.addEventListener('mousedown', function(e) {
		if (e.target === this) {
			setTimeout(() => this.children[0].focus(), 0);
		}
	});
	
	//Prevent Enter. See purpose in "Step 2" in answer.
	el.parentNode.addEventListener('keydown', function(e) {
		if (e.keyCode === 13)
			e.preventDefault();
	});
});
.CETextInputBorder { /*This element is needed to prevent cursor: text on border*/
	display: inline-block;
	border: 1px solid #aaa;
}

.CETextInputCont {
	overflow: hidden;
	cursor: text; /*You must set it because parent elements is bigger then child contenteditable element. Also you must add javascript to focus child element on click parent*/
	
	/*Style:*/
	width: 10em;
	height: 1em;
	line-height: 1em;
	padding: 5px;
	font-size: 20px;
	font-family: sans-serif;
}

.CETextInput {
	white-space: pre; /*"pre" is like "nowrap" but displays all spaces correct (with "nowrap" last space is not displayer in Firefox, tested on Firefox 66, 2019-05-15)*/
	overflow-x: auto;
	min-height: 100%; /*to prevent zero-height with no text*/
	
	/*We will duplicate vertical padding to let user click contenteditable element on top and bottom. We would do same thing for horizontal padding but it is not working properly (in all browsers when scroll is in middle position and in Firefox when scroll is at the end). You can also replace vertical padding with just bigger line height.*/
	padding: 5px 0;
	margin-top: -5px;
	
	outline: none; /*Prevent border on focus in some browsers*/
}
<div class="CETextInputBorder">
	<div class="CETextInputCont">
		<div class="CETextInput" contenteditable></div>
	</div>
</div>

Ответ 9

с jQuery Я установил событие .keypress, а затем проверил для e.keyCode == 13 (return key), и если возвращается false из события, и редактирование не способно создавать многостроки

$('*[contenteditable=yes]').keypress(function(e) {
  if(e.keyCode == 13 && !$(this).data('multiline')) {
    return false;
  }
})