ENTER - Chrome'da içerikli <div> eklemeyi önleyin


131

Bir contenteditableelemanım var ve ne zaman bir şeyler yazsam ve vurduğumda ENTERyeni bir tane yaratıyor <div>ve yeni satır metnini oraya yerleştiriyor. Bundan hiç hoşlanmadım.

Bunun olmasını önlemek veya en azından bir ile değiştirmek mümkün müdür <br>?

İşte demo http://jsfiddle.net/jDvau/

Not: Bu, firefox'ta bir sorun değildir.


1
firefox <br>, chrome - değil ekler, ancak stillerinizi düzelttikten sonra fazladan div'ler sol dolguyu bozmaz. Soru, neden beğenmediğiniz? Bunun br ... jsfiddle.net/jDvau/1 Ayrıca bu div'leri yakalamak ve kaldırmak için DOMSubtreeModified olayını kullanabilirsiniz.
ViliusL

stackoverflow.com/questions/6024594/… bu size yardımcı olabilir, iyi şanslar!
Sirikon

1
Bana göre Blake Plumb'ın çözümü burada en basit ve en iyisi.
svassr

1
@svassr mesele bu değil, onu kullanacak olan sen veya ben değil, değişimin ne olduğunu bile bilmeyen bir müşteri olabilir.
iConnor

2
Aslında her şeyi değiştirir. Bu, yaygın bir davranış olduğunu ve küçük bir yardım mesajının devreye girmeyeceğini söyledi. "Bir adama bir balık verin ve onu bir günlüğüne besleyin. Bir adama balık tutmayı öğretin ve onu bir ömür boyu besleyin."
svassr

Yanıtlar:


161

Bunu dene:

$('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;
    }
});

Demo için burayı tıklayın


Ama burada küçük bir fark buluyorum. İmlecinizi sadece boş satıra getirin ("Bir şeyler yazın" ın üstüne) ve enter tuşuna basın. İmleç artık yeni boş satırda değil, "Tür" ün hemen önündedir.
Andrew

3
Bu, insertHTML'yi desteklemediği için IE11'de çalışmaz. Aşağıdaki cevaba bakın!
webprogrammer

4
İmlecinizi karakterler arasına koyarsanız, örneğin. 'Ty [imleç] pe bazı şeyler' ve enter tuşuna basın, çok fazla 1 satır alıyorsunuz.
Chandrew

13
Cevap kabul edilemez. Çözüm yalnızca bir tane olması olabilir <br />
raoulinski

3
bu dönüş hem <br> hem de <div>
Nishad

51

Bunu sadece bir CSS değişikliğiyle yapabilirsiniz:

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

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

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


1
Satır içi blok kullandığımda, herhangi bir şey eklemek için execCommand ("insertHTML", xxx) çalıştırdığımda bir sorun oluştu, eklenen öğenin sonuna bir "<br>" eklenecek, Chrome33'te test edildi.
Imskull

5
Güzel keşif. Maalesef bu konum üzerinde çalışmaz: mutlak öğeler veya ekranlı bir ebeveynin doğrudan çocukları olan öğeler: esnek. Bunu aklınızdan çıkarmadan çalışmak için hackleyebilirsiniz. Bunun esnek unsurların doğrudan bir çocuğu olmadığından emin olun. Pozisyona ihtiyacınız varsa: mutlak sadece bununla fazladan bir ebeveyn verin.
Şüpheci

@ReinoutvanKempen 3 ay önce flex kullanmaya başladı. Sanırım bu hack işe yaramayacak
kittu

bu gerçekten harika bir çözüm, son derece temiz ve net, hiçbir şey eklenmeyecek, hatta br dahil. ve özellikle js içermeyen bu çözüm.
savun

2
Vay be ... bu Chrome'u çözüyor, ancak Firefox'un varsayılan olarak yapmadığı enter'a div'ler eklemesini sağlıyor.
cbdeveloper

40

Stil ekleyin display:inline-block;etmek contenteditable, bu oluşturmaz div, pve spanotomatik olarak Chrome'da.


6
Bu harika bir çözüm. *[contenteditable="true"]{display: inline-block;}
ericjbasti


IE11'de bu bir ekstra yapacak <p></p> :(
Betty St

1
ancak çok sinir bozucu başka bir Chrome hatası oluşturacak (ne boktan bir tarayıcı)
vsync

4
Chrome 63.0.3239.84 Sürümü ile artık çalışmıyor
Mikaël Mayer

21

Bunu dene:

$('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/


Güzel, işe yarıyor :) Karar vermeden önce daha fazla ilgi bekleyeceğim, teşekkürler.
iConnor

firefox'ta düzgün çalışmıyor. fazladan bir satır ekler.
2016

Bu, inputenter tuşuna bastığınızda tetiklenmemesini sağlar. Basit bir çözüm: $(this).trigger('input')
Şuna

insertHTMLSolüsyon iç içe orada tuhaflaştırıyor contenteditable, elemanlar çözüm alt ettiği o ancak biraz daha sorunlar vardır, ben yeni olası bir çözüm olarak bunu ekledi.
skerit

Chrome'da çalışmıyor. Dizenin sonunda enter tuşuna ilk kez bastığınızda, bir boşluk ekler. İkinci seferde işe yarıyor.

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

Bunun yerine paragrafa sahip olmak için varsayılan davranışı geçersiz kılar.

Chrome'da enter'daki varsayılan davranış şudur:

<div>
    <br>
</div>

Bu komutla olacak

<p>
    <br>
</p>

Artık daha doğrusal olduğu için, yalnızca <br>ihtiyacınız olana sahip olmak kolaydır .


Enter tuşuna bastığınızda, div ve br yerine p ve br tarayıcıya sahip olacaksınız. Dene.
Ced 25'16

Teşekkürler! Açıklamalar her zaman faydalıdır
jpaugh

@jpaugh np, cevabımı daha iyi açıklamak için daha fazla düzenledim.
Ced 25'16

bu firefox'ta çalışmıyor (sadece Chrome ve Firefox'ta test ettim)
medBouzid

FireFox, artık defaultParagraphSeparator'a uyacak şekilde düzeltildi. IMHO bu, tüm tarayıcıları artık tutarlı ve spesifikasyonla uyumlu hale getirdiği için bu yanıtı en iyi yapar. Daha sonra bir P etiketinin, düzenlenebilir içerikteki önceki metin bloğundan bir marj 'aralığına' sahip olmasını istemiyorsanız, bunu değiştirmek için css kullanabilirsiniz.
blackmamba

9

Kullanım shift+ enteryerine entersadece tek bir koyun <br>içinde etiketi veya daki metni kaydırma <p>etiketleri.


9
+1 Teşekkürler, bunu bilmek çok kullanışlı, ancak kitap yazan bir müşteriniz varsa, bu ***
iConnor

1
Bu, içerik yapıştırıyorsanız yardımcı olmaz
vsync

5

contenteditableBastığınızda nasıl davranacağı entertarayıcılara bağlıdır <div>, webkit (chrome, safari) ve IE'de olur.

Birkaç ay önce bununla mücadele ettim ve şu şekilde düzelttim:

//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);
            }
        }
    });
}

Umarım yardımcı olur ve gerektiği kadar net değilse ingilizcem için özür dilerim.

DÜZENLEME : Kaldırılan jQuery işlevinin düzeltilmesijQuery.browser


Sadece bilmeniz için, jQuery.browserartık jQuery'nin bir parçası değil.
iConnor

Doğru ettik, bunu belirtmeliyim ve kullanım gibi bir şey navigator.userAgent.indexOf("msie") > 0venavigator.userAgent.indexOf("webkit") > 0
Elie

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

5

<p>Etiketleri kullanmak yerine her satır için ayrı etiketlere sahip olabilir <br>ve kutudan daha iyi bir tarayıcı uyumluluğu elde edebilirsiniz.

Bunu yapmak için <p>, memnun edici div'in içine bazı varsayılan metinler içeren bir etiket koyun .

Örneğin, bunun yerine:

<div contenteditable></div>

kullanın:

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

jsfiddle

Chrome, Firefox ve Edge'de test edilmiştir ve ikincisi her birinde aynı şekilde çalışır.

Ancak ilki, Chrome'da div'ler oluşturur, Firefox'ta satır sonları oluşturur ve Edge'de div'ler oluşturur ve imleç bir sonrakine geçmek yerine geçerli div'in başına geri getirilir.

Chrome, Firefox ve Edge'de test edilmiştir.


bu aslında kötü bir çözüm değil
AaronHS

5

Kısayol tuşlarını işlemek için Fare Kapanı'nı kullanmayı seviyorum: https://craig.is/killing/mice

Ardından, enter olayını yakalayıp insertLineBreak komutunu çalıştırıyorum :

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

Tüm komutlar: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Chrome 75 ve aşağıdaki düzenlenebilir öğeyi kullanarak çalışır:

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

Ayrıca insertHTML kullanmak da mümkündür :

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

4

div'e bir önleme varsayılanı ekle

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

@connorspiracist üzgünüm document.body.div( divsadece genel fikri düzeltmek için muhtemelen başka bir kod girmeniz gerekecek )
Math chiller

4

Sorunu düzeltmek için stil (Css) kullanırım.

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

Firefox gerçekten bir blok öğesi sonu ekler
, Chrome ise her bölümü bir etiketle sarar. Sen css divs bir dolgu verir 10px arka plan rengiyle birlikte.

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

Alternatif olarak, istenen aynı etkiyi jQuery'de çoğaltabilirsiniz:

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

İşte kemanınızın bir çatalı http://jsfiddle.net/R4Jdz/7/


1
Bu bazı insanlara yardımcı olabilir, ancak son HTML'sini alıp contenteditablebaşka bir yerde
kullanacağım

3

Paragraflarınızı <p>etiketle sarmalayabilirsiniz, örneğin div yerine yeni satırda görünecektir Örnek:
<div contenteditable="true"><p>Line</p></div>
Yeni dize ekledikten sonra:
<div contenteditable="true"><p>Line</p><p>New Line</p></div>


3

inserHTMLKomut çözümü iç içe olması tuhaflaştırıyor contenteditableelemanları.

Burada birçok cevaptan bazı fikirler aldım ve bu şimdilik ihtiyaçlarıma uyuyor gibi görünüyor:

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

Öncelikle, enter'a basılıp basılmadığını görmek için girilen her anahtarı yakalamamız gerekiyor, ardından <div>oluşturmayı engelliyoruz ve kendi <br>etiketimizi oluşturuyoruz.

Bir sorun var, onu oluşturduğumuzda imlecimiz aynı konumda kalıyor, bu yüzden imlecimizi sona yerleştirmek için Seçim API'sini kullanıyoruz .

<br>Metninizin sonuna bir etiket eklemeyi unutmayın çünkü yapmazsanız ilk giriş yeni bir satır oluşturmaz.

$('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();
        }
    }
});

Vaktini boşa harcamak


2

Bu, tarayıcı tarafından yönlendirilen HTML5 editörüdür. Metninizi ile kaydırabilirsiniz <p>...</p>, ardından ENTER tuşuna her bastığınızda alırsınız <p></p>. Ayrıca, düzenleyici bu şekilde çalışır, ÜST KARAKTER + ENTER tuşlarına bastığınızda bunu ekler <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>

Şunu kontrol edin: http://jsfiddle.net/ZQztJ/


2

Bu, tüm büyük tarayıcılarda çalışır (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>

Bir rahatsızlık var. Düzenlemeyi bitirdikten sonra, öğelerin <br>içinde bir son bulunabilir . Ancak gerekirse, bunu azaltmak için kod ekleyebilirsiniz.

Sondaki https://stackoverflow.com/a/61237737/670839'u kaldırmak için bu yanıtı kontrol <br> edin


Ne halt? Benim için gerçekten işe yarayan tek çözüm sayfanın bu kadar aşağısında nasıl olabilir? Çok teşekkürler.
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>')

thisYani gerçek bağlam nerede document.getElementById('test');.


0

Bunu yapmanın başka bir yolu

$('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/


Siz yazarken imlecin ilerlemesine izin vermez.
Jack Lu

Bu garip, sadece Chrome ve IE 11'de denedim ve iyi çalışıyor. Referans Lütfen bana hangi tarayıcıyı kullandığınızı söyler misiniz? Davranışla ilgili daha fazla ayrıntı sorunun çözülmesine yardımcı olacaktır
MrAJ

0

Her enter tuşunda içerik düzenlenebilir Div'de Yeni Div oluşturulmasını önleyin: Bulduğum çözüm çok basit:

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

Bu --- innerHTML içeriği, her giriş tuşunda düzenlenebilir Div içeriğinde Yeni Div oluşturulmasını engeller.


0

W3C Editör Taslağında, ContentEditable'a durum ekleme hakkında bazı bilgiler vardır ve enter tuşuna basıldığında tarayıcının yeni eleman eklemesini önlemek için kullanabilirsiniz plaintext-only.

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

-1

Bu davranışı tamamen engellemek mümkündür.

Bu kemanı görün

$('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.