2012-02-01 14 views
58

Ho cercato di chiedere questo prima, senza alcuna fortuna di spiegare/dimostrare un esempio funzionante in cui si verifica l'errore. Quindi, ecco un altro tentativo:Segnaposto in contenteditable - problema evento focus

Sto tentando di replicare un effetto segnaposto su un DIV contenteditable. Il concetto di base è semplice:

<div contenteditable><em>Edit me</em></div> 

<script> 
$('div').focus(function() { 
    $(this).empty(); 
}); 
</script> 

Questo può sometomes lavoro, ma se il segnaposto contiene HTML, o se c'è qualche altra elaborazione in corso, cursore del testo della modificabile del DIV viene rimosso, e l'utente deve ri-click il DIV modificabile per essere in grado di iniziare a scrivere (anche se è ancora a fuoco):

Esempio: http://jsfiddle.net/hHLXr/6/

non posso utilizzare un trigger di messa a fuoco nel gestore, dal momento che creerà un ciclo di eventi. Quindi ho bisogno di un modo per reimpostare il cursore del cursore sul DIV modificabile o in altri modi per mettere a fuoco.

risposta

23

Potrebbe essere necessario aggiornare manualmente la selezione. In IE, l'evento di messa a fuoco è troppo tardi, quindi suggerirei di utilizzare l'evento activate. Ecco alcuni codice che fa il lavoro in tutti i principali browser, tra cui Internet Explorer < = 8 (che un'alternativa CSS-only non sarà):

demo dal vivo: http://jsfiddle.net/hHLXr/12/

Codice:

$('div').on('activate', function() { 
    $(this).empty(); 
    var range, sel; 
    if ((sel = document.selection) && document.body.createTextRange) { 
     range = document.body.createTextRange(); 
     range.moveToElementText(this); 
     range.select(); 
    } 
}); 

$('div').focus(function() { 
    if (this.hasChildNodes() && document.createRange && window.getSelection) { 
     $(this).empty(); 
     var range = document.createRange(); 
     range.selectNodeContents(this); 
     var sel = window.getSelection(); 
     sel.removeAllRanges(); 
     sel.addRange(range); 
    } 
}); 
+0

Un altro +1 per * RangeMaster *. Ho pensato di mantenere le cose semplici eviterei i problemi del cross browser, ma è stato piuttosto ingenuo da parte mia. –

+0

Dolce! Speravo che saresti stato con me. Rangemaster! – David

+1

@AndyE: Grazie. Potrebbe esserci un modo più semplice. Dovrebbe esserci, davvero, ma non sono riuscito a trovarne uno in fretta. –

0
var curText = 'Edit me'; 
$('div').focusin(function() { 
    if ($(this).text().toLowerCase() == curText.toLowerCase() || !$(this).text().length) { 
     $(this).empty(); 
    } 
}).focusout(function() { 
    if ($(this).text().toLowerCase() == curText.toLowerCase() || !$(this).text().length) { 
     $(this).html('<em>' + curText + '</em>'); 
    } 
}); 
+0

Grazie, ma il problema non è che non so come salvare il testo segnaposto, ma il fatto che il cursore scompare quando si cancella il testo segnaposto. – David

20

solo usa le pseudo-classi css.

span.spanclass:empty:before {content:"placeholder";} 
+1

Funziona come un incantesimo. – ccleve

+1

Funziona proprio come il comportamento del segnaposto nativo, perfetto! – CatalinBerta

27

Ho appena published a plugin for this.

Esso utilizza una combinazione di CSS3 e JavaScript per mostrare il segnaposto senza aggiungere al contenuto del div:

HTML:

<div contenteditable='true' data-placeholder='Enter some text'></div> 

CSS:

div[data-placeholder]:not(:focus):not([data-div-placeholder-content]):before { 
    content: attr(data-placeholder); 
    float: left; 
    margin-left: 5px; 
    color: gray; 
} 

JS:

(function ($) { 
    $('div[data-placeholder]').on('keydown keypress input', function() { 
     if (this.textContent) { 
      this.dataset.divPlaceholderContent = 'true'; 
     } 
     else { 
      delete(this.dataset.divPlaceholderContent); 
     } 
    }); 
})(jQuery); 

E questo è tutto.

+3

whoa! .......... – tim

+1

NB: Da quando ho scritto questa risposta, ho aggiornato il plug-in per gli elementi di compatibilità IE e non 'div'. Vedi il repository GitHub collegato per l'ultima versione. –

+0

Funziona se sto impostando il testo 'div' dal backend? Nel mio caso segnaposto e il mio testo sono concessi – demo

149

Ecco un CSS unica soluzione aumentando alcune delle altre risposte: -

<div contentEditable=true data-ph="My Placeholder String"></div> 
<style> 
    [contentEditable=true]:empty:not(:focus)::before{ 
     content:attr(data-ph) 
    } 
</style> 

EDIT: Ecco il mio frammento su codepen ->http://codepen.io/mrmoje/pen/lkLez

EDIT2: Essere informati, questo metodo non funziona al 100% per applicazioni multilinea a causa degli elementi residui <br> presenti nel div dopo aver eseguito uno select-all-cut o select-all-delete su tutte le linee.Credits: - @vsync
Backspace sembra funzionare bene (almeno su WebKit/blink)

+1

Questo sarebbe eccezionalmente interessante, tranne ... non riesco a farlo funzionare. Puoi pubblicare un jsfiddle funzionante? – ccleve

+0

@ccleve Controlla la mia modifica. Spero non ti dispiaccia usare il mio codepen. Jsfiddle ha agito su me parecchio (e trovo che i codepen hanno caratteristiche migliori) – moje

+7

Questa dovrebbe essere la risposta accettata. È un po 'più complicato di quello di @amwinter ma mantiene il segnaposto in html anziché in css. – ccleve

4

Qui è il mio modo:

Esso utilizza una combinazione di jQuery e CSS3. Funziona esattamente come l'attributo placeholder html5!.

  • si nasconde subito quando si immette la prima lettera
  • si mostra ancora una volta quando si elimina ciò che si immette in esso

HTML:

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

CSS3:

.placeholder:after { 
    content: "Your placeholder"; /* this is where you assign the place holder */ 
    position: absolute; 
    top: 10px; 
    color: #a9a9a9; 
} 

jQuery:

$('.placeholder').on('input', function(){ 
    if ($(this).text().length > 0) { 
     $(this).removeClass('placeholder'); 
    } else { 
     $(this).addClass('placeholder'); 
    } 
}); 

DEMO: http://jsfiddle.net/Tomer123/D78X7/

+0

L'evento 'input' è piuttosto nuovo in elementi contenteditable. Ad esempio, non è supportato affatto in IE. –

8

Ho trovato che il modo migliore per farlo è quello di utilizzare l'attributo placeholder come al solito e aggiungere alcune righe di CSS.

HTML

<div contenteditable placeholder="I am a placeholder"></div> 

CSS

[contenteditable][placeholder]:empty:before { 
    content: attr(placeholder); 
    color: #bababa; 
} 

Nota: il selettore CSS :empty funziona solo se non c'è letteralmente nulla in-tra l'apertura e tag di chiusura. Questo include nuove linee, schede, spazio vuoto, ecc

Codepen

+0

Questa soluzione ha un problema in FF.sul bordo vicino a destra se si fa clic due volte, il cursore si blocca lì. – mayankcpdixit

1

Ecco la correzione che ho usato.

<div contenteditable><em>Edit me</em></div> 
<script> 
$('div').focus(function() { 
    var target = $(this); 
    window.setTimeout(function() { target.empty(); }, 10); 
}); 
</script> 

Ho sviluppato un plug-in jQuery per questo. Date un'occhiata https://github.com/phitha/editableDiv

6

Tutto ciò che serve è questa piccola soluzione

[contenteditable=true]:empty:before{ 
    content: attr(placeholder); 
    display: block; /* For Firefox */ 
} 

Demo:http://codepen.io/flesler/pen/AEIFc

+0

Funziona. Testato in firefox, chrome e Safari. –

+0

Occhio, ma non Bordo (il cursore appare alla fine) – cgat

0

Questo non è soluzione esatta del problema ..

nelle opzioni summernote set

airMode: vero

segnaposto funziona in questo modo.

Problemi correlati