简体   繁体   中英

Using contenteditable to create auto-resizing textareas

After reading some of Chris Coyier's musing about auto growing textareas, I was experimenting with using the concept for an email form. But as is often the case I am running into browser inconsistencies in regard to the actual html content created.

I have been experimenting with using div, span and p as my targets. And then using js innerHTML to grab the end result. Edge and Chrome seem to treat things the same (logical since they have the same engine), Firefox gives different results (not sure about Safari since I don't iAnything).

Basic html

<div class="label">groupcode</div>
<div id="gid" class="pseudo" contenteditable> </div>
<div class="label">subject</div>
<div id="sbj" class="pseudo" contenteditable> </div>
<div class="label">message</div>
<div id="msg" class="pseudo" contenteditable> </div>
<button id="btn">Submit</button>

Script

  document.getElementById('btn').addEventListener('click', function() {
    var tid = document.getElementById('gid').textContent;
    var sbj = document.getElementById('sbj').textContent;
    var msg = document.getElementById('msg').innerHTML;
    console.log(msg);
    var data = new URLSearchParams();
    data.append('gid', gid);
    data.append('sbj', sbj);
    data.append('msg', msg);

    const url = 'https://path-to-domain/test.php';
    fetch(url, {
      method: 'post',
      body: data,
    })
    .then(function (response) {
        return response.text();
      })
    .then(function (html) {
      // This is the HTML from our response as a text string
      document.getElementById('rsults').innerHTML = html;
    });
  });

Testing the pseudo form with:

Hello [[name]],

Howzit going?

Bye bye.

Firefox using span or p as contenteditable target produces the following with innerHTML:

Hello [[name]],<br><br>Howzit going?<br><br>Bye bye.<br>

Firefox using div as contenteditable target produces the following with innerHTML:

<div>Hello [[name]],</div><div><br></div><div>Howzit going?</div><div><br></div><div>Bye bye<br></div>

Edge and Chrome using span, p or div as contenteditable target all produce the following with innerHTML:

Hello [[name]],<div><br></div><div>Howzit going?</div><div><br></div><div>Bye bye.</div>

Are there any ways to get a consistent output from contenteditable? Or am I limited to building in a browser detection to strip the excess div in the PHP that processes the pseudo-form's data? Or use span and tell everyone in the business to use Firefox (since Firefox's span and p outputs are usable as is).

As explained here , this inconsistency is expected. You might improve the situation a little by setting defaultParagraphSeparator with document.execCommand , but bear in mind that this method is deprecated . The safest bet seems to be consolidating html codes, which you could try inside the addEventListener function. Here is one example of the defaultParagraphSeparator method. In my system, the only difference between Firefox and Chrome is the wrapping of the first line.

 document.execCommand("defaultParagraphSeparator", false, "p"); document.getElementById('btn').addEventListener('click', function() { var tid = document.getElementById('gid').textContent; var sbj = document.getElementById('sbj').textContent; var msg = document.getElementById('msg').innerHTML; console.log(msg); var data = new URLSearchParams(); data.append('gid', gid); data.append('sbj', sbj); data.append('msg', msg); const url = 'https://path-to-domain/test.php'; fetch(url, { method: 'post', body: data, }) .then(function (response) { return response.text(); }) .then(function (html) { // This is the HTML from our response as a text string document.getElementById('rsults').innerHTML = html; }); });
 <div class="label">groupcode</div> <div id="gid" class="pseudo" contenteditable="true"> </div> <div class="label">subject</div> <div id="sbj" class="pseudo" contenteditable="true"> </div> <div class="label">message</div> <div id="msg" class="pseudo" contenteditable="true"> </div> <button id="btn">Submit</button>

After experimenting with several browsers, we opted to do some string manipulation in js before sending the "form" contents to its PHP processing. We haven't tested all browsers, so some additional replace might be needed.

All the browsers seemed to use div and br to separate sections, so we started with the biggest string which all browsers produced for two line breaks. Then the partial string that Chrome produces due to not wrapping the first line. Then processed the smaller two tag strings such as <br></div> and finally checked if there was a leading tag, adding one if not.

// replace double line breaks with </p><p>
msg = msg.replaceAll('</div><div><br></div><div>', '</p><p>');

// replace first double line break with </p><p> on Chromium browsers
msg = msg.replace('<div><br></div><div>', '</p><p>');

// replace single line breaks with <br>
msg = msg.replaceAll('</div><div>', '<br>');

// strip leading and trailing tags and replace with <p> or </p>
msg = msg.replace('<br></div>', '</p>').replace('</div>', '</p>').replace('<div>', '<p>');

// check if leading <p>, append if not, primarily Chromium browsers
if (msg.startsWith('<p>') === false) {
  msg = '<p>' + msg;
}

Processing the replace & replaceAll from longest string to shortest was crucial.

Using editable divs instead of textareas makes the interface nicer. Allowing the user to view the entire email as they write, same as the recipient will see it, not as text in an input that you have to scroll to read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM