Placeholder in contenteditable - focus event issue - javascript

I have been trying to ask this before, without any luck of explaining/proving a working example where the bug happens. So here is another try:
I’m trying to replicate a placeholder effect on a contenteditable DIV. The core concept is simple:
<div contenteditable><em>Edit me</em></div>
<script>
$('div').focus(function() {
$(this).empty();
});
</script>
This can sometomes work, but if the placeholder contains HTML, or if there some other processing being made, the editable DIV’s text caret is being removed, and the user must re-click the editable DIV to be able to start typing (even if it’s still in focus):
Example: http://jsfiddle.net/hHLXr/6/
I can’t use a focus trigger in the handler, since it will create an event loop. So I need a way to re-set the caret cursor in the editable DIV, or in some other way re-focus.

Here is a CSS only solution augmenting some of the other answers:-
<div contentEditable=true data-ph="My Placeholder String"></div>
<style>
[contentEditable=true]:empty:not(:focus)::before{
content:attr(data-ph)
}
</style>
EDIT: Here is my snippet on codepen -> http://codepen.io/mrmoje/pen/lkLez
EDIT2: Be advised, this method doesn't work 100% for multi-line applications due to residual <br> elements being present in the div after performing a select-all-cut or select-all-delete on all lines. Credits:- #vsync
Backspace seems to work fine (at least on webkit/blink)

I've just published a plugin for this.
It uses a combination of CSS3 and JavaScript to show the placeholder without adding to the content of the 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);
And that's it.

You may need to manually update the selection. In IE, the focus event is too late, so I would suggest using the activate event instead. Here's some code that does the job in all major browsers, including IE <= 8 (which a CSS-only alternative will not):
Live demo: http://jsfiddle.net/hHLXr/12/
Code:
$('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);
}
});

just use css pseudo-classes.
span.spanclass:empty:before {content:"placeholder";}

I found that the best way to do this is to use the placeholder attribute like usual and add a few lines of CSS.
HTML
<div contenteditable placeholder="I am a placeholder"></div>
CSS
[contenteditable][placeholder]:empty:before {
content: attr(placeholder);
color: #bababa;
}
Note: the CSS :empty selector only works if there is literally nothing in-between the opening and closing tag. This includes new lines, tabs, empty space, etc.
Codepen

All you need is this little solution
[contenteditable=true]:empty:before{
content: attr(placeholder);
display: block; /* For Firefox */
}
Demo: http://codepen.io/flesler/pen/AEIFc

Here's my way:
It uses a combination of jQuery and CSS3. Works exactly like the html5 placeholder attribute!.
Hides itself right away when you input the first letter
Shows itself again when you delete what you input into it
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/

Here's the fix that I used.
<div contenteditable><em>Edit me</em></div>
<script>
$('div').focus(function() {
var target = $(this);
window.setTimeout(function() { target.empty(); }, 10);
});
</script>
I developed a jQuery plug-in for this. Take a look https://github.com/phitha/editableDiv

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

This is not exact solution of your problem ..
in summernote options set
airMode:true
placeholder works in this way.

In .css
.holder:before {
content: attr(placeholder);
color: lightgray;
display: block;
position:absolute;
font-family: "Campton", sans-serif;
}
in js.
clickedOnInput:boolean = false;
charactorCount:number = 0;
let charCount = document.getElementsByClassName('edit-box')[0];
if(charCount){
this.charactorCount = charCount.innerText.length;
}
if(charactorCount > 0 && clickedOnInput){
document.getElementById("MyConteditableElement").classList.add('holder');
}
if(charactorCount == 0 && !clickedOnInput){
document.getElementById("MyConteditableElement").classList.remove('holder');
}
getContent(innerText){
this.clickedOnInput = false;
}
In .html
<div placeholder="Write your message.." id="MyConteditableElement" onclick="clickedOnInput = true;" contenteditable class="form-control edit-box"></div>
this solution worked for me in angular project

Related

Adding 'placeholder' text to an element using JS

-
There are a few posts on this already (like this one) but they're not really adaptable to this situation.
I have a shortcode that dynamically generates text content based on a custom field in my CRM, this is used to display a users serial number for their software, shown below:
The direct parent container for the serial number is #copyTarget2.
When the container is empty it is still rendered on the page but with no content, shown here:
I need to populate the empty container with 'placeholder' text, but not the kind that you can type over, just so that there is text visible that just reads - 'No active serial number.'
Lastly, when the field is populated, the placeholder text needs to be hidden, it doesn't really matter how it's hidden so long as it's not visible and doesn't affect the text generated by the shortcode.
I also tried to adapt this JS Fiddle: http://jsfiddle.net/davidThomas/LAfN2/
From:
$('input:text').each(
function(i,el) {
if (!el.value || el.value == '') {
el.placeholder = 'placeholdertext';
/* or:
el.placeholder = $('label[for=' + el.id + ']').text();
*/
}
});
To:
jQuery('#copyTarget2').each(
function(i,el) {
if (!el.value || el.value == '') {
el.placeholder = 'No valid serial number.';
/* or:
el.placeholder = $('label[for=' + el.id + ']').text();
*/
}
});
CSS and HTML are like second languages to me but I'm new to JS so I can modify code a little but I can't write it (yet), I'm wondering what the best JS solution would be to achieve this and why?
Using :empty and :before with attribute to set the placeholder when it is empty.
[data-placeholder]:empty:before {
color: #AAA;
content: attr(data-placeholder);
}
<span data-placeholder="My placeholder"></span>
<br/>
<span data-placeholder="My placeholder">I have text</span>
I think you need a effect like placeholder in the span element not the input tag .Try with some css .see the below snippet .And add the attribute using attr() of jquery function
see the CSS content
jQuery('#copyTarget2').each(
function(i, el) {
if (!$(el).text() || $(el).text().trim() == '') {
$(el).attr('placeholder', 'No valid serial number.')
/* or:
el.placeholder = $('label[for=' + el.id + ']').text();
*/
}
});
span:empty:before {
font-size: 12;
color: #9E9E9E;
line-height: 40px;
text-indent: 20px;
content: attr(placeholder);
display: block;
border: 1px solid grey;
}
span{
position:absolute;/*or fix as your wish with respect to parent element*/
width:200px;/*or fix as your wish with respect to parent element*/
height:50px;/*or fix as your wish with respect to parent element*/
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="copyTarget2"></span>

How to get selected text with JavaScript

I'm a little confused why doesn't this code work!
The HTML Markup:
<div id="diva"><b>Score</b> some <i>goals</i></div>
<div id="soda"></div>
The JavaScript code:
function GetSelectedText () {
if (window.getSelection) { // all browsers, except IE before version 9
var range = window.getSelection ();
alert (range.toString ());
}
else {
if (document.selection.createRange) { // Internet Explorer
var range = document.selection.createRange ();
alert (range.text);
}
}
}
var butn = document.getElementById("soda");
butn.onclick = function(){
GetSelectedText();
}
One problem that you may well be experiencing is that in some browsers (notably IE), by the time the button's click event fires, the selection has been destroyed. You can fix this by using the mousedown event instead (which still allows the selection to be destroyed, but only after the event has been handled), or by making the button unselectable.
I assume your button is not an actual button input, because this behaviour only happens for regular elements.
Demo: http://jsfiddle.net/L9bvU/1/
function GetSelectedText () {
if (window.getSelection) { // all browsers, except IE before version 9
var range = window.getSelection ();
alert (range.toString ());
}
else {
if (document.selection.createRange) { // Internet Explorer
var range = document.selection.createRange ();
alert (range.text);
}
}
}
span {
background-color: #ccc;
padding: 3px;
border: solid gray 1px;
}
*[unselectable="on"] {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
/*
Introduced in IE 10.
See http://ie.microsoft.com/testdrive/HTML5/msUserSelect/
*/
-ms-user-select: none;
user-select: none;
}
<div contenteditable="true">Please select some of this text and press a button below</div>
<span onclick="GetSelectedText()">Click</span>
<span onmousedown="GetSelectedText()">Mousedown</span>
<span unselectable="on" onclick="GetSelectedText()">Click, unselectable</span>
function getSelectedText() {
if (window.getSelection) {
return window.getSelection();
}
if (window.document.getSelection) {
return window.document.getSelection();
}
if (window.document.selection) {
return window.document.selection.createRange().text;
}
return "";
}
<p onmouseup="getSelectedText(); alert(txt)">
Highlight some of this text
with the mouse select press button end release
to fire the event. </p>
This is my way. You just need to select the text end alert text or anything else.
Does anyone know how OnMouse(event) set for the entire document in html, and it does not have to be directly added to html page.
To be on the other side, as we can change the elements in firebug!>-examples
Well there are two problems with the above code.
-You can't be guaranteed that
var butn = document.getElementById("soda");
will work because it may execute before the document is done loading
-When you click on another element that's not a button, the selection is lost. If you change the "soda" div to then it will work:
<div id="diva"><b>Score</b> some <i>goals</i></div>
<div id="soda" onclick="GetSelectedText()">This will NOT work</div>
<input type="button" onclick="GetSelectedText()" value="This will work"/>
However I strongly recommend you look at jQuery as the others here have advised; it will make your like a lot easier!

Watermark for contenteditable div element

I have "contenteditable" div element. I want to set a watermark for it so that when user tries to write something in the div the watermark should go disappear.
I tried some watermark jQuery plugins, all work for input, textarea. What is the way to implement this feature for contenteditable div?
If you by "watermark" mean like a placeholder effect, the concept should be fairly simple:
var mark = 'Watermark',
edited = false;
$('[contenteditable]').focus(function() {
if(!edited) {
$(this).empty();
}
}).blur(function() {
if(!$(this).html()) {
$(this).html(mark);
}
}).keyup(function() {
edited = true;
}).text(mark);
Demo: http://jsfiddle.net/jjxvR/1/
Here's my answer to another question:
It uses a combination of jQuery and CSS3. Works exactly like the html5 placeholder attribute!.
Hides itself right away when you input the first letter
Shows itself again when you delete what you input into it
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/
I solved it this way:
div[contenteditable]:empty:before {
content: '-';
}
div[contenteditable]:focus:before {
color: transparent;
}

How do I erase the background of a field when the user types something?

I have a search field which basically gives the user a "tip" of what to search (which is the background image). I need to erase the background when he types something. But I'm not sure how.
This is the searchfield:
<input style="font-size:20px; width:300px; color: #444; background: url('http://chusmix.com/Imagenes/busca.png') white;" type="text" id="s" name="s" onblur="if(this.value == '') { this.style.background='url(http://chusmix.com/Imagenes/busca.png) no-repeat 0% 50% white';}">
Is there an easy way to do it? If you need more info please ask. Thanks
Add this little bit of javascript in the tag: onFocus='this.value=""';
I think you want to get rid of the onblur and instead make it onfocus (so the background changes when they enter the box).. or even onchange so whenever they type it goes away.
I am using Facebook like plugin from here
http://github.com/loopj/jQuery-Tokenizing-Autocomplete-Plugin
I just had a go at this one and it was really easy to implement using an asp.net page to output the JSON (from the search params) Then theres just a few lines of Javascript you need to create it (and the settings)
$(document).ready(function() {
$("#Users").tokenInput("../Services/Job/UnassignedUsers.aspx?p=<%= projectID %>&j=<%= jobID %>", {
hintText: "Begin typing the user name of the person you wish to assign.",
noResultsText: "No results",
searchingText: "Searching..."
});
});
Hope this might help you
Assume txtTopSearchBox is the id of text box and "Search" is the content on that (tip)
$(document).ready(function() {
$("#txtTopSearchBox").focus(function() {
$(this).removeClass().addClass("txtSearchBoxFocus").val("");
});
$("#txtTopSearchBox").blur(function() {
if (($(this).val() == "Search") || ($(this).val() == "")) {
$(this).removeClass().addClass("txtSearchBox").val("Search");
}
});
$("#txtTopSearchBox").keypress(function(e) {
if (e.which == 13) {
var key = $("#txtTopSearchBox").val();
key = escape(key);
window.location.href = "browse.aspx?search=" + key;
return false;
}
});
});
Tested and works in Fx 3.6, Safari 5 and Chrome. Image too big for field when not copying the attributes to the withoutTip too
<style type="text/css">
.withTip {
font-size:20px;
width:300px;
color: #444;
background: white url(http://chusmix.com/Imagenes/busca.png) }
.withoutTip { background: white url()}
</style>
<input class="withTip" type="text" id="s" name="s"
onkeyup="this.className=(this.value=='')?'withTip':'withoutTip'" />
or
<style type="text/css">
#s {font-size:20px; width:300px; color: #444;}
.withTip { background: white url(http://chusmix.com/Imagenes/busca.png) }
.withoutTip { background: white url()}
</style>
If you are interested in html5, the upcoming placeholder attribute will take care of this. But alas, not all browsers are html5 ready. The second sub-heading on this page shows browser compatibility.
Until then, the JavaScript method PMV describes works well.

How can I position a label inside its textfield?

I have many textfields that show instruction text within the textbox (how the default value would look). On focus the color of the text becomes lighter, but doesn't go away until text is entered. When text is erased, the label returns. It's pretty slick. A default value doesn't cut it, because these go away onfocus.
I have it working, but the code is complicated because it relies on negative margins that correspond to the individual widths of the textfields. I want a dynamic solution where the label for its textfield is positioned correctly automatically, probably using a script.
Any help would be greatly appreciated. But I am not looking for default values as a solution.
Thanks.
Mike
Edited to be more precise.
Edited again to provide some simple code that illustrates the effect I am after:
<input style="position: relative; width: 150px; font-size: 10px; font-family: Verdana, sans-serif; " type="text" name="name" id="name"
onfocus="javascript: document.getElementById('nameLabel').style.color='#BEBEBE';"
onkeypress="javascript: if (event.keyCode!=9) {document.getElementById('nameLabel').innerHTML=' ';}"
onkeyup="javascript: if (this.value=='') document.getElementById('nameLabel').innerHTML='Your Name';"
onblur="javascript: if (this.value=='') {document.getElementById('nameLabel').style.color='#7e7e7e'; document.getElementById('nameLabel').innerHTML='Your Name';}"/>
<label id="nameLabel" for="name" style="position: relative; margin-left: -150px; font-size: 10px; font-family: Verdana, sans-serif;">Your Name</label>
I would have taken a different approach (It's not entirely my idea, but i can't find the source for credit):
1st - Use html5 "placeholder" property.
2nd - Use Modernizr.js to detect support of placeholders in the browser and a simple jQuery script to add support to browsers that doesn't support it.
So, the html will look something like that:
<input type="text" class="placeholder" placeholder="Help Text" />
<textarea class="placeholder" placeholder="Another help text"></textarea>
The css:
.placeholder{color:#ccc;}
And the javascript:
/* Set placeholder for browsers that don't support HTML5 <input placeholder='text'>
* Depends on Modernizr v1.5
*/
if (!Modernizr.input.placeholder){
$('input[placeholder], textarea[placeholder]')
.focus(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
})
.blur(function() {
var input = $(this);
if (input.val() == '') {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
}
})
//Run once on load
.blur();
// Clear all 'placeholders' on submit
$('input[placeholder], textarea[placeholder]').parents('form').submit(function() {
$(this).find('[placeholder]').each(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
}
});
});
}
What you are asking here is probably what is called textbox watermark.
For this, you usually don't use a label (control) inside a textfield. Instead you replace the content of the textfield when the real content of the text field is empty with some text using certain CSS property and then remove it once you blur out (w/ additional check to see if the text inside the textbox itself is the same as the watermark text. If it is, blank the field again.)
Try this. It's pretty simple implementation of this using jquery and css.
Here's one that I borrowed from somewhere:
$(function() {
// Give the textbox a watermark
swapValues = [];
$('.your_input_class').each(function(i){
$(this).val("Please enter xyz");
swapValues[i] = $(this).val();
$(this).focus(function(){
if ($(this).val() == swapValues[i]) {
$(this).val("").css("color", "#333");
}
}).blur(function(){
if ($.trim($(this).val()) == "") {
$(this).val(swapValues[i]).css("color", "#ccc");
}
});
});
});
And then for your input box:
<input class="your_input_class" type="text" value="" />
It remembers the value that is stored in it when the page loads (well, I'm setting mine directly in the JS) and it also changes the color when it's focused/not focused.
Do you mean like this? But instead of 'required' it would have the label?
I used a jQuery solution where I set the value of the input to 'required'. The input has a class of gray so the default text is lighter.
Edit after comment
Instead of using focus, you can change the input values on keydown and keyup.
$('.required_input').keydown(function()
{
if (this.value == 'required')
{
$(this).val('').removeClass('gray');
}
} );
$('.required_input').keyup(function()
{
if (this.value == '')
{
$(this).val('required').addClass('gray');
}
} );
$('.required_input').blur(function()
{
if (this.value == '')
{
$(this).val('required').addClass('gray');
}
} );
<script type="text/javascript">
window.onload = function(){
inputs = document.getElementsByTagName("input");
for(i = 0; i < inputs.length;i++){
var feild = inputs[i];
if(feild.type == "text"){
var label = document.getElementById(feild.id + "Label");
label.style.left = "-" + feild.clientWidth;
}
}
}
</script>
This bit of script should do what you wanted

Categories

Resources