Cegah penambahan konten yang dapat diedit <div> pada ENTER - Chrome


131

Saya memiliki contenteditableelemen, dan setiap kali saya mengetik beberapa barang dan menekannya ENTERmenciptakan yang baru <div>dan menempatkan teks baris baru di sana. Saya tidak suka yang ini sedikit pun.

Apakah mungkin untuk mencegah hal ini terjadi atau setidaknya hanya menggantinya dengan <br>?

Inilah demo http://jsfiddle.net/jDvau/

Catatan: Ini bukan masalah di firefox.


1
firefox menambahkan Situs, chrome - tidak, tetapi setelah memperbaiki gaya Anda, div tambahan tidak merusak bantalan kiri. Pertanyaannya adalah mengapa Anda tidak menyukainya? Pikirkan itu adalah ... jsfiddle.net/jDvau/1 Anda juga dapat menggunakan acara DOMSubtreeModified untuk menangkap div ini dan menghapusnya.
ViliusL

stackoverflow.com/questions/6024594/... ini bisa membantu Anda, semoga berhasil!
Sirikon

1
Bagi saya solusi Blake Plumb adalah yang paling sederhana dan dari jauh yang terbaik di sini.
svassr

1
@svassr bukan itu intinya, bukan Anda atau saya yang akan menggunakannya, Ini klien yang bahkan mungkin tidak tahu apa itu shift.
iConnor

2
Memang itu mengubah segalanya. Yang mengatakan itu adalah perilaku umum dan pesan bantuan kecil tidak akan mempersenjatai. "Beri seorang pria ikan dan kamu memberinya makan selama sehari. Ajari seorang pria untuk memancing dan kamu memberinya makan seumur hidup."
svassr

Jawaban:


161

Coba ini:

$('div[contenteditable]').keydown(function(e) {
    // trap the return key being pressed
    if (e.keyCode === 13) {
        // insert 2 br tags (if only one br tag is inserted the cursor won't go to the next line)
        document.execCommand('insertHTML', false, '<br/>');
        // prevent the default behaviour of return key pressed
        return false;
    }
});

Klik di sini untuk demo


Tetapi saya menemukan sedikit perbedaan di sini. Letakkan kursor Anda tepat di baris kosong (di atas "Ketik beberapa barang"), dan tekan enter. Kursor sekarang tepat sebelum "Type", bukan pada baris kosong baru.
Andrew

3
Ini tidak berfungsi di IE11 karena tidak mendukung insertHTML. Lihat jawaban di bawah!
webprogrammer

4
Jika Anda meletakkan kursor di antara karakter misalnya. 'Ty [cursor] pe some stuff' dan tekan enter, Anda mendapatkan 1 baris terlalu banyak.
Chandrew

13
Jawaban tidak dapat diterima. Solusi akan memiliki hanya satu <br />
raoulinski

3
ini mengembalikan Situs dan <div>
Nishad Naik

51

Anda dapat melakukan ini hanya dengan perubahan CSS:

div{
    background: skyblue;
    padding:10px;
    display: inline-block;
}

pre{
    white-space: pre-wrap;
    background: #EEE;
}

http://jsfiddle.net/ayiem999/HW43Q/


1
Ada masalah ketika saya menggunakan inline-block, jalankan execCommand ("insertHTML", xxx) untuk memasukkan apa pun, "<br>" akan ditambahkan di akhir elemen yang dimasukkan, diuji di Chrome33.
Imskull

5
Temuan yang bagus. Sayangnya ini tidak akan berfungsi pada posisi: elemen absolut atau elemen yang merupakan anak langsung dari orang tua dengan tampilan: fleksibel. Anda dapat meretasnya agar berfungsi dengan mengingatnya. Pastikan itu bukan anak langsung dari elemen fleksibel. Jika Anda membutuhkannya posisi: absolut berikan saja orangtua tambahan dengan itu.
Skeptis

@ReinoutvanKempen Mulai menggunakan flex 3 bulan lalu. Saya kira peretasan ini tidak akan berhasil
kittu

ini adalah solusi yang benar-benar hebat, sangat bersih dan jelas, tidak ada yang akan dimasukkan, bahkan termasuk br. dan terutama solusi ini tanpa js.
membela orca

2
Wow ... ini memecahkan Chrome, tetapi membuat Firefox mulai menambahkan div saat masuk, yang tidak secara default.
cbdeveloper

40

Menambah gaya display:inline-block;ke contenteditable, itu tidak akan menghasilkan div, pdan spansecara otomatis di Chrome.


6
Ini solusi hebat. *[contenteditable="true"]{display: inline-block;}
ericjbasti

Menyukainya, sederhana namun efektif
user25794

Di IE11 ini akan menghasilkan tambahan <p></p> :(
Betty St

1
tetapi itu akan membuat bug Chrome yang sangat menyebalkan (browser yang buruk)
vsync

4
Tidak berfungsi lagi dengan Versi Chrome 63.0.3239.84
Mikaël Mayer

21

Coba ini:

$('div[contenteditable="true"]').keypress(function(event) {

    if (event.which != 13)
        return true;

    var docFragment = document.createDocumentFragment();

    //add a new line
    var newEle = document.createTextNode('\n');
    docFragment.appendChild(newEle);

    //add the br, or p, or something else
    newEle = document.createElement('br');
    docFragment.appendChild(newEle);

    //make the br replace selection
    var range = window.getSelection().getRangeAt(0);
    range.deleteContents();
    range.insertNode(docFragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(newEle);
    range.collapse(true);

    //make the cursor there
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    return false;
});

http://jsfiddle.net/rooseve/jDvau/3/


Bagus, bekerja :) Saya akan menunggu lebih banyak perhatian sebelum saya memutuskan, terima kasih.
iConnor

tidak berfungsi dengan benar di firefox. itu menambahkan satu baris tambahan.
agpt

Ini membuatnya agar inputtidak terpicu ketika Anda menekan enter. Sebuah solusi sederhana: tambahkan sth like$(this).trigger('input')
LarsW

The insertHTMLsolusi melakukan beberapa hal-hal aneh ketika ada bersarang contenteditableelemen, solusi circumvents Anda bahwa tetapi ada beberapa masalah yang lebih, saya menambahkan sebagai solusi baru mungkin.
skerit

Tidak berfungsi di Chrome. Pertama kali ketika Anda menekan enter di akhir string, itu menambah spasi. Namun yang kedua kali berhasil.

20
document.execCommand('defaultParagraphSeparator', false, 'p');

Itu menimpa perilaku default untuk memiliki paragraf sebagai gantinya.

Pada chrome, perilaku default pada enter adalah:

<div>
    <br>
</div>

Dengan perintah itu akan terjadi

<p>
    <br>
</p>

Sekarang karena lebih linier, Anda hanya <br>perlu melakukannya dengan mudah.


Saat Anda menekan enter, alih-alih memiliki div dan br, Anda akan memiliki p dan br di browser. Cobalah.
Ced

Terima kasih! Penjelasan selalu membantu
jpaugh

@ jpaugh np, saya mengedit jawaban saya lebih jauh sehingga itu menjelaskan lebih baik.
Ced

ini tidak bekerja pada firefox (saya diuji hanya pada chrome dan firefox)
medBouzid

FireFox telah diperbaiki untuk sekarang menghormati defaultParagraphSeparator. IMHO ini membuat jawaban ini yang terbaik karena membuat semua browser sekarang konsisten dan sesuai dengan spesifikasi. Jika Anda kemudian tidak ingin tag P memiliki margin 'spasi' dari blok teks sebelumnya dalam konten yang dapat diedit maka Anda dapat menggunakan css untuk memodifikasinya.
blackmamba

9

Gunakan shift+ enteralih-alih enterhanya memasukkan satu <br>tag atau membungkus teks Anda dengan <p>tag.


9
+1 Terima kasih, ini sangat mudah untuk diketahui, tetapi jika Anda memiliki klien yang menulis buku, itu akan sangat
menyebalkan

1
Ini tidak membantu jika Anda menempelkan konten
vsync

5

Cara contenteditableberperilaku ketika Anda menekan entertergantung pada browser, yang <div>terjadi pada webkit (chrome, safari) dan IE.

Saya berjuang dengan ini beberapa bulan lalu dan saya memperbaikinya dengan cara ini:

//I recommand you trigger this in case of focus on your contenteditable
if( navigator.userAgent.indexOf("msie") > 0 || navigator.userAgent.indexOf("webkit") > 0 ) {
    //Add <br> to the end of the field for chrome and safari to allow further insertion
    if(navigator.userAgent.indexOf("webkit") > 0)
    {
        if ( !this.lastChild || this.lastChild.nodeName.toLowerCase() != "br" ) {
            $(this).html( $(this).html()+'<br />' );
        }
    }

    $(this).keypress( function(e) {
        if( ( e.keyCode || e.witch ) == 13 ) {
            e.preventDefault();

            if( navigator.userAgent.indexOf("msie") > 0 ) {
                insertHtml('<br />');
            }
            else {
              var selection = window.getSelection(),
              range = selection.getRangeAt(0),
              br = document.createElement('br');

              range.deleteContents();
              range.insertNode(br);
              range.setStartAfter(br);
              range.setEndAfter(br);
              range.collapse(false);

              selection.removeAllRanges();
              selection.addRange(range);
            }
        }
    });
}

Saya harap ini akan membantu, dan maaf untuk bahasa Inggris saya jika tidak sejelas yang diperlukan.

EDIT : Koreksi fungsi jQuery dihapusjQuery.browser


Sekadar memberi tahu Anda, jQuery.browserbukan lagi bagian dari jQuery.
iConnor

Anda benar, saya harus menyebutkan ini dan menggunakan sesuatu seperti navigator.userAgent.indexOf("msie") > 0dannavigator.userAgent.indexOf("webkit") > 0
Elie

1
if( ( e.keyCode || e.witch ) == 13 ) { ... }perluif (e.keyCode === 13 || e.which === 13) { ... }
Sebastian Sandqvist

5

Anda dapat memiliki <p>tag terpisah untuk setiap baris daripada menggunakan <br>tag dan mendapatkan kompatibilitas browser yang lebih besar di luar kotak.

Untuk melakukan ini, letakkan <p>tag dengan beberapa teks default di dalam div yang dapat diedit.

Misalnya, alih-alih:

<div contenteditable></div>

Menggunakan:

<div contenteditable>
   <p>Replace this text with something awesome!</p>
</div>

jsfiddle

Diuji di Chrome, Firefox, dan Edge, dan yang kedua bekerja sama di masing-masing.

Namun, yang pertama membuat div di Chrome, membuat jeda baris di Firefox, dan di Edge menciptakan div dan kursor dikembalikan ke awal div saat ini alih-alih pindah ke yang berikutnya.

Diuji di Chrome, Firefox, dan Edge.


ini sebenarnya bukan solusi yang buruk
AaronHS

5

Saya suka menggunakan perangkap tikus untuk hotkey handlling: https://craig.is/killing/mice

Lalu, saya baru saja mencegat acara masuk, menjalankan perintah insertLineBreak :

Mousetrap.bindGlobal('enter', (e)=>{
  window.document.execCommand('insertLineBreak', false, null);
  e.preventDefault();
});

Semua perintah: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Ia bekerja menggunakan Chrome 75 dan elemen yang dapat diedit berikut:

<pre contenteditable="true"></pre>

Dimungkinkan juga untuk menggunakan insertHTML :

window.document.execCommand('insertHTML', false, "\n");

4

tambahkan mencegah default ke div

document.body.div.onkeydown = function(e) {
    if ( e.keycode == 13 ){
        e.preventDefault();
            //add a <br>
        div = document.getElementById("myDiv");
        div.innerHTML += "<br>";
    }
}

@connorspiracist maaf document.body.div(Anda mungkin perlu memasukkan beberapa kode lain untuk memperbaiki divhanya ide umumnya)
Math chiller

4

Saya akan menggunakan styling (Css) untuk memperbaiki masalah ini.

div[contenteditable=true] > div {
  padding: 0;
} 

Firefox memang menambahkan break elemen blok
, sedangkan Chrome membungkus setiap bagian dalam tag. Anda css memberikan pads pad 10px bersama dengan warna latar belakang.

div{
  background: skyblue;
  padding:10px;
}

Atau, Anda dapat meniru efek yang diinginkan di jQuery:

var style = $('<style>p[contenteditable=true] > div { padding: 0;}</style>');
$('html > head').append(style);

Ini adalah garpu biola Anda http://jsfiddle.net/R4Jdz/7/


1
Ini mungkin membantu beberapa orang, tetapi saya lebih peduli tentang markup yang tidak penting, karena saya akan mengambil HTML final contenteditabledan menggunakannya di tempat lain
iConnor

3

Anda dapat membungkus paragraf Anda dengan <p>tag misalnya akan muncul pada baris baru, bukan div Contoh:
<div contenteditable="true"><p>Line</p></div>
Setelah memasukkan string baru:
<div contenteditable="true"><p>Line</p><p>New Line</p></div>


3

The inserHTMLsolusi perintah melakukan beberapa hal aneh ketika Anda memiliki bersarang contenteditableelemen.

Saya mengambil beberapa ide dari beberapa jawaban di sini, dan ini tampaknya sesuai dengan kebutuhan saya untuk saat ini:

element.addEventListener('keydown', function onKeyDown(e) {

    // Only listen for plain returns, without any modifier keys
    if (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) {
        return;
    }

    let doc_fragment = document.createDocumentFragment();

    // Create a new break element
    let new_ele = document.createElement('br');
    doc_fragment.appendChild(new_ele);

    // Get the current selection, and make sure the content is removed (if any)
    let range = window.getSelection().getRangeAt(0);
    range.deleteContents();

    // See if the selection container has any next siblings
    // If not: add another break, otherwise the cursor won't move
    if (!hasNextSibling(range.endContainer)) {
        let extra_break = document.createElement('br');
        doc_fragment.appendChild(extra_break);
    }

    range.insertNode(doc_fragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(new_ele);
    range.collapse(true);

    //make the cursor there
    let sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    e.stopPropagation();
    e.preventDefault();

    return false;
});

// See if the given node has a next sibling.
// Either any element or a non-empty node
function hasNextSibling(node) {

    if (node.nextElementSibling) {
        return true;
    }

    while (node.nextSibling) {
        node = node.nextSibling;

        if (node.length > 0) {
            return true;
        }
    }

    return false;
}


2

Pertama kita perlu menangkap setiap pengguna kunci masuk untuk melihat apakah masuk ditekan maka kita mencegah <div>penciptaan dan kita buat sendiri<br> tag .

Ada satu masalah, ketika kita membuatnya, kursor kita tetap pada posisi yang sama sehingga kita menggunakan API Pemilihan untuk menempatkan kursor kita di akhir.

Jangan lupa untuk menambahkan <br>tag di akhir teks Anda karena jika Anda tidak memasukkan entri pertama tidak akan membuat baris baru.

$('div[contenteditable]').on('keydown', function(e) {
    var key = e.keyCode,
        el  = $(this)[0];
    // If Enter    
    if (key === 13) {
        e.preventDefault(); // Prevent the <div /> creation.
        $(this).append('<br>'); // Add the <br at the end

        // Place selection at the end 
        // http://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
        if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
            var range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(false);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (typeof document.body.createTextRange != "undefined") {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.collapse(false);
            textRange.select();
        }
    }
});

Biola


2

Ini adalah editor HTML5 yang diarahkan oleh browser. Anda dapat membungkus teks Anda dengan <p>...</p>, maka setiap kali Anda menekan ENTER Anda dapatkan <p></p>. Juga, editor bekerja dengan cara ini sehingga setiap kali Anda menekan SHIFT + ENTER, sisipan <br />.

<div contenteditable="true"><p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor veniam asperiores laudantium repudiandae doloremque sed perferendis obcaecati delectus autem perspiciatis aut excepturi et nesciunt error ad incidunt impedit quia dolores rerum animi provident dolore corporis libero sunt enim. Ad magnam omnis quidem qui voluptas ut minima similique obcaecati doloremque atque!
<br /><br />
Type some stuff, hit ENTER a few times, then press the button.
</p>
</div>

Lihat ini: http://jsfiddle.net/ZQztJ/


2

Ini berfungsi di semua browser utama (Chrome, Firefox, Safari, Edge)

document.addEventListener('keydown', event => {
  if (event.key === 'Enter') {
    document.execCommand('insertLineBreak')
    event.preventDefault()
  }
})
<div class="element" contenteditable="true">Sample text</div>
<p class="element" contenteditable="true">Sample text</p>

Ada satu ketidaknyamanan. Setelah Anda selesai mengedit, elemen-elemen tersebut mungkin mengandung akhiran <br>di dalamnya. Tetapi Anda dapat menambahkan kode untuk memotongnya jika perlu.

Periksa jawaban ini untuk menghapus trailing <br> https://stackoverflow.com/a/61237737/670839


Apa apaan? Bagaimana satu-satunya solusi yang benar-benar bekerja untuk saya sejauh ini? Terima kasih banyak.
user12861

1
if (navigator.userAgent.toLowerCase().indexOf('msie') > -1) {
   var range = document.getSelection();
   range.pasteHTML(range.htmlText + '<br><br>');
}
else if(navigator.userAgent.toLocaleLowerCase().indexOf('trident') > -1)                           {
   var range = document.getSelection().getRangeAt(0); //get caret
   var nnode = document.createElement('br');
   var bnode = document.createTextNode('\u00A0'); //&nbsp;
   range.insertNode(nnode);
   this.appendChild(bnode);
   range.insertNode(nnode);                                
}
else
   document.execCommand('insertHTML', false, '<br><br>')

Dimana thiskonteks aktual yang artinya document.getElementById('test');.


0

Cara lain untuk melakukannya

$('button').click(function(){
    $('pre').text($('div')[0].outerHTML)
});

$("#content-edit").keydown(function(e) {
    if(e.which == 13) {
       $(this).find("div").prepend('<br />').contents().unwrap();
      }
});

http://jsfiddle.net/jDvau/11/


Itu tidak membiarkan kursor bergerak maju saat Anda mengetik.
Jack Lu

Itu aneh, saya baru mencoba di Chrome dan IE 11 dan berfungsi dengan baik. Referensi Bisakah Anda memberi tahu saya browser mana yang Anda gunakan? Rincian lebih lanjut tentang perilaku ini akan sangat membantu untuk menyelesaikan masalah ini
MrAJ

0

Cegah pembuatan Div Baru di konten yang dapat diedit Div pada setiap tombol enter: Solusi yang saya temukan sangat sederhana:

var newdiv = document.createElement("div"); 
newdiv.innerHTML = "Your content of div goes here";
myEditablediv.appendChild(newdiv);

Konten --- innerHTML ini mencegah pembuatan Div Baru di konten yang dapat diedit Div pada setiap tombol enter.


0

Pada Draft Editor W3C ada beberapa informasi tentang menambahkan status ke ContentEditable , dan untuk mencegah browser untuk menambahkan elemen baru saat menekan enter yang dapat Anda gunakan plaintext-only.

<div contentEditable="plaintext-only"></div>

-1

Dimungkinkan untuk sepenuhnya mencegah perilaku ini.

Lihat biola ini

$('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.