Renderowanie HTML wewnątrz obszaru tekstowego

146

Muszę mieć możliwość renderowania niektórych tagów HTML wewnątrz obszaru tekstowego (mianowicie <strong>, <i>, <u>, <a>), ale obszary tekstowe interpretują ich zawartość tylko jako tekst. Czy istnieje łatwy sposób na zrobienie tego bez polegania na zewnętrznych bibliotekach / wtyczkach (używam jQuery)? Jeśli nie, czy znasz jakąś wtyczkę jQuery, której mógłbym użyć do tego?

Kodujący mnich
źródło
Jedynym sposobem na to będzie nałożenie znaczników HTML na zawartość tagu textarea za pomocą sztuczek pozycjonowania CSS. Nic nie pomoże Ci przekonać przeglądarki do odmiennego renderowania zawartości Textarea. (Dlaczego właściwie „musisz” to zrobić?)
Pointy
Potrzebuję tylko, aby użytkownik mógł dodać kilka stylów formatowania do wprowadzanego tekstu (podobnie jak podczas pisania artykułu w Wordpress). Po prostu nie potrzebuję wszystkich funkcji, takich jak wyrównanie tekstu i tak dalej, ale tylko te podstawowe znaczniki.
The Coding Monk

Odpowiedzi:

234

Nie można tego zrobić z plikiem textarea. To, czego szukasz, to edytowalny element div, który można bardzo łatwo zrobić:

<div contenteditable="true"></div>

jsFiddle

div.editable {
    width: 300px;
    height: 200px;
    border: 1px solid #ccc;
    padding: 5px;
}

strong {
  font-weight: bold;
}
<div contenteditable="true">This is the first line.<br>
See, how the text fits here, also if<br>there is a <strong>linebreak</strong> at the end?
<br>It works nicely.
<br>
<br><span style="color: lightgreen">Great</span>.
</div>

mekwall
źródło
8
szkoda, że ​​nie możesz praktycznie tego użyć bez użycia javascript, aby przesłać swoje zmiany za pomocą Ajax lub skopiować je do formularza. Jeśli ktoś znalazł na to sposób, byłbym bardzo zainteresowany!
Ben
3
@yckart: Cóż, nie sądzę, żeby to faktycznie było poprawne, mimo że działa we wszystkich przeglądarkach, które próbowałem. contenteditablejest atrybutem wyliczanym, a nie atrybutem boolowskim (istnieje również inheritstan oraz truei false) i myślę, że oznacza to, że określenie wartości jest obowiązkowe, chociaż nie mogę znaleźć ostatecznego fragmentu specyfikacji, aby to potwierdzić. Wydaje się jednak, że MDN się z tym zgadza .
Tim Down
2
@yckart: Założyłem, że przeglądarka interpretuje contenteditablebez wartości jako to samo co contenteditable="", co z kolei jest tym samym co contenteditable="true".
Tim Down
7
To nie działa lepiej niż textarea. Wpisanie <strong>someting</strong>na skrzypce pozostawia dokładnie ten tekst. Kod HTML nie jest stosowany.
Matt Ellen,
2
@MarcusEkwall, ale czy pytanie nie dotyczyło renderowania HTML?
phil294
31

W przypadku edytowalnego elementu div możesz użyć metody document.execCommand( więcej szczegółów ), aby w łatwy sposób zapewnić obsługę określonych tagów i inne funkcje.

#text {
    width : 500px;
	min-height : 100px;
	border : 2px solid;
}
<div id="text" contenteditable="true"></div>
<button onclick="document.execCommand('bold');">toggle bold</button>
<button onclick="document.execCommand('italic');">toggle italic</button>
<button onclick="document.execCommand('underline');">toggle underline</button>

Sampath Liyanage
źródło
To nie działa w niektórych przeglądarkach, po prostu dodając to jako notatkę z roku
2016
5

Ponieważ powiedziałeś tylko render, tak, możesz. Możesz zrobić coś w ten sposób:

function render(){
	var inp     = document.getElementById("box");
	var data = `
<svg xmlns="http://www.w3.org/2000/svg" width="${inp.offsetWidth}" height="${inp.offsetHeight}">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" 
style="font-family:monospace;font-style: normal; font-variant: normal; font-size:13.3px;padding:2px;;">
${inp.value} <i style="color:red">cant touch this</i>
</div>
</foreignObject>
</svg>`;
	var blob = new Blob( [data], {type:'image/svg+xml'} );
	var url=URL.createObjectURL(blob);
	inp.style.backgroundImage="url("+URL.createObjectURL(blob)+")";
 }
 onload=function(){
  render();
  ro = new ResizeObserver(render);
	ro.observe(document.getElementById("box"));
 }
#box{
  color:transparent;
  caret-color: black;
  font-style: normal;/*must be same as in the svg for caret to align*/
  font-variant: normal; 
  font-size:13.3px;
  padding:2px;
  font-family:monospace;
}
<textarea id="box" oninput="render()">you can edit me!</textarea>
To sprawia, że textareabędzie renderował html! Poza miganiem podczas zmiany rozmiaru, niemożnością bezpośredniego użycia klas i koniecznością upewnienia się, że element div w elemencie svgma taki sam format jak w textareaprzypadku prawidłowego wyrównania daszka, to działa!

merlin
źródło
2

Dodatek do tego. Możesz używać encji znakowych (takich jak zmiana <div>na &lt;div&gt;), a renderuje się w obszarze tekstowym. Jednak po zapisaniu wartością pola tekstowego jest renderowany tekst . Więc nie musisz dekodować. Właśnie przetestowałem to w różnych przeglądarkach (tj. Z powrotem do 11).

axlotl
źródło
Naprawdę chciałbym, żeby to zadziałało, ale tak się nie stało. Na przykład <textarea> check for url &lt;B&gt;http://localhost/Dashboard.aspx&lt;/B&gt; &lt;BR&gt; Tool Started at &lt;B&gt;11/10/2015 3:56:58 AM&lt;/B&gt; &lt;BR&gt; .... </textarea>nie wyświetla się jako HTML. Jestem na Chrome 46.
sirdank
Hm. Skopiowałem ten ciąg bezpośrednio do dokumentu HTML i poprawnie renderuje znaczniki w Chrome w wersji 48.0.2552.0 dev (64-bit) OS X 10.11.1. Więc może to problem z wersją.
axlotl
Wciąż
axlotl
0

Mam ten sam problem, ale w odwrotnej kolejności i następujące rozwiązanie. Chcę umieścić kod HTML z elementu DIV w obszarze tekstowym (aby móc edytować niektóre reakcje na mojej stronie internetowej; chcę, aby obszar tekstowy znajdował się w tej samej lokalizacji).

Aby umieścić zawartość tego div w obszarze tekstowym, którego używam:

var content = $('#msg500').text();
$('#msg500').wrapInner('<textarea>' + content + '</textarea>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="msg500">here some <strong>html</strong> <i>tags</i>.</div>

Houdini
źródło
0

spróbuj tego przykładu

function toggleRed() {
  var text = $('.editable').text();
  $('.editable').html('<p style="color:red">' + text + '</p>');
}

function toggleItalic() {
  var text = $('.editable').text();
  $('.editable').html("<i>" + text + "</i>");
}

$('.bold').click(function() {
  toggleRed();
});

$('.italic').click(function() {
  toggleItalic();
});
.editable {
  width: 300px;
  height: 200px;
  border: 1px solid #ccc;
  padding: 5px;
  resize: both;
  overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="editable" contenteditable="true"></div>
<button class="bold">toggle red</button>
<button class="italic">toggle italic</button>

david grinstein
źródło
-2

Jest to możliwe, <textarea> ponieważ jedyne, co musisz zrobić, to użyć edytora Summernote WYSIWYG

interpretuje znaczniki HTML wewnątrz textarea (mianowicie <strong>, <i>, <u>, <a>)

Fenil Shah
źródło
Nie używa textarea. Używa div, którego nie można przesłać za pomocą formularza.
Usman Ahmed
Działa z textarea, po prostu spróbuj podać id textarea zamiast div. Stworzyłem cały projekt używając textarea i summernote. To działa dobrze!
Fenil Shah
Jaki jest sens? Zachowuje się tak samo jak ckeditor, jeśli używany jest textarea. Nie można renderować tagów HTML zgodnie z pytaniem
Usman Ahmed
Dlaczego powinienem używać edytora WYSIWYG? To naprawdę nie jest odpowiedź, przepraszam.
Luca De Nardi