How to create a "placeholder" for DIV that act like textfield? - html

Div don't have a placeholder attribute
<div id="editable" contentEditable="true"></div>
I want <Please your enter your Name> to show in DIV when the User backspace the whole text in the DIV, or no text on inside, How can I do it?

Here is a pure CSS only solution:-
<div contentEditable=true data-ph="My Placeholder String"></div>
<style>
[contentEditable=true]:empty:not(:focus):before{
content:attr(data-ph)
}
</style>
Here, we basically select all contentEditable <divs> that are empty & blurred. We then create a pseudo element before the CSS selection (the editable div) and fix our placeholder text (specified the data-ph attribute) as its content.
If you are targeting old school CSS2 browsers, change all occurrences of data-ph to title
Correction.......the :empty selector is not supported in IE version 8 and earlier.

What I find in other answers is that when using :not(:focus) pseudo class, I have to click again in order to get the blinking cursor and be able to type. Such issue doesn't happen if I click on an area other than the placeholder.
My workaround is simply removing :not(:focus). Even though in this way the placeholder will still be there after I click on the editable div, I'm able to type no matter where in the div I click, and the placeholder disappears immediately after I type something.
BTW, I inspected YouTube's comment div implementation, seems they are doing the same thing, e.g. #contenteditable-root.yt-formatted-string[aria-label].yt-formatted-string:empty:before
.editableDiv1,
.editableDiv2 {
border-bottom: 1px solid gray;
outline: none;
margin-top: 20px;
}
.editableDiv1[contentEditable="true"]:empty:not(:focus):before {
content: attr(placeholder)
}
.editableDiv2[contentEditable="true"]:empty:before {
content: attr(placeholder)
}
<div class="editableDiv1" contentEditable=true placeholder="If you click on this placeholder, you have to click again in order to get the blinking cursor and type..."></div>
<div class="editableDiv2" contentEditable=true placeholder="Click on placeholder is fine, it'll disappear after you type something..."></div>

You can try this one !
html:
<div contentEditable=true data-text="Enter name here"></div>
css:
[contentEditable=true]:empty:not(:focus):before{
content:attr(data-text) }
check it out (demo)

in HTML
<div id="editable" contenteditable="true">
<p>Please your enter your Name</p>
</div>
in JavaScript
jQuery.fn.selectText = function(){
var doc = document;
var element = this[0];
console.log(this, element);
if (doc.body.createTextRange) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
};
$("#editable").click(function() {
$("#editable").selectText();
});
jsFiddle

Related

angular ngModel style

Is it possible to style the value in the attribute ngModel of an input tag?
Example:
<input class="input" type="text" [(ngModel)] = "myService.text">
Let's say the value of text is '28 packages', can I put 28 in bold?
So if i understand correctly you want to have it bold whenever the value is 28 ?
yes its possible you can use a ng-class with a ternary expression like this
.bold{
font-weight:600;
}
<input type="text" ng-class="myService.text == '28 ? 'bold' : '''" class="input" ng-model="myService.text" />
This is not angular-related rather a CSS related question.
You cannot style only a part of an input in HTML/CSS so you won't be able to do it in angular.
Instead, you can use an input that is hidden behind a div. The idea is that when the user clicks the div, you actually focus the input. When the user types text, you capture the content of the input and fill the div with it, eventually adding <span class"highlight"> around the number of packages.
I prepared you a stackblitz in pure CSS/JS. You can adapt it in angular if you want.
Relevant pieces of code :
HTML :
<span id="hiddenSpan">This is the hidden div. Click it and start typing</span>
<div>
<label for="in">The real input</label>
<input id="in" type="text">
</div>
JS :
const input = document.getElementById('in')
const hiddenSpan = document.getElementById('hiddenSpan')
function onInputChanged() {
let text = input.value
const regex = new RegExp('(\\d+) packages')
let result = regex.exec(text)
if(result) {
hiddenSpan.innerHTML = '<span class="highlight">'+result[1]+'</span> packages'
} else {
hiddenSpan.innerHTML = text
}
}
// Capture keystrokes.
input.addEventListener('keyup', onInputChanged)
// Focus the input when the user clicks the pink div.
hiddenSpan.addEventListener('click', function() {
input.focus()
})
CSS :
#hiddenSpan {
background-color: pink;
}
.highlight {
font-weight: bold;
background-color: greenyellow;
}
Note : the downside is that the blinking caret is not visible anymore. You can take a look at this resource if you want to simulate one.
It is not possible to style certain parts of a text <input> field in bold. However, you can use a contenteditable div instead of a text <input> field. Inside the contenteditable div you can have other HTML tags like <strong> to style certain parts of the text however you like.
I created an Angular directive called contenteditableModel (check out the StackBlitz demo here) and you can use it to perform 2-way binding on a contenteditable element like this:
<div class="input" contenteditable [(contenteditableModel)]="myService.text"></div>
The directive uses regular expressions to automatically check for numbers in the inputted text, and surrounds them in a <strong> tag to make them bold. For example, if you input "28 packages", the innerHTML of the div will be formatted like this (to make "28" bolded):
<strong>28</strong> packages
This is the code used in the directive to perform the formatting:
var inputElement = this.elementRef.nativeElement;
inputElement.innerHTML = inputElement.textContent.replace(/(\d+)/g, "<strong>$1</strong>");
this.change.emit(inputElement.textContent);
You can change the <strong> tag to something else (e.g. <span style="text-decoration: underline"> if you want the text to be underlined instead of bolded).
When performing the formatting, there is an issue where the user's text cursor position will be unexpectedly reset back to the beginning of the contenteditable div. To fix this, I used 2 functions (getOriginalCaretPosition and restoreCaretPosition) to store the user's original cursor position and then restore the position back after the text formatting is performed. These 2 functions are kind of complex and they're not entirely relevant to the OP's question so I will not go into much detail about them here. You can PM me if you want to learn more about them.

put text on div with out affecting hover

I just tried putting text over my video. The video autostarts when hovering it. With the Text on it the hover is "disabled". Is there any option to display the text without effecting the hover? Text is absolute.
I use a js to start the video. The Text is in a div on top.
window.onload = function() { //executes this code after the DOM loads
//--- this is the selector element. Feel free to change this if you don't want all video objects targeted.
const vids = document.getElementsByTagName(`video`)
//--- Now we loop over all of the selected elements and add event listeners
for (let i = 0; i < vids.length; i++) {
vids[i].addEventListener( `mouseover`, function(e) {
vids[i].play()
})
vids[i].addEventListener( `mouseout`, function(e) {
vids[i].pause()
})
}
}
Image from Webinspector
So you can add the two following css properties to the text object so that the user cannot interact with them.
.text-class {
user-select: none;
pointer-events: none;
}
If you still want the users to be able to select the text, say if copy & pasting the text is important you can just do.
.text-class {
pointer-events: none;
}

text_input: Placeholder keeps RTL while only change input to be LTR

The text-input now is RTL(both placeholder and the input). The attributes were set at some where else.
My question is how can I make a change that only changes the input to be LTR, while the placeholder remains RTL.
Example:
Initially, the text box is like
When it gets focus, the input should be LTR. Because the URL is LTR.
If user didn't type anything and the box lost focus, the placeholder should show up and keep RTL.
Can anyone help me with this? Thanks.
You can use this code.
//jQuery
(function($) {
$.fn.dir_auto = function() {
var selector = '.inputs-nyn[dir="auto"]';
var sclass = "auto-nyn05";
var ftime = true;
if ( $(selector).length ) {
$(document).on("keyup", selector , function() {
if( ftime || !$(this).val() ){
if( !$(this).val() ){
$(this).addClass(sclass);
ftime = true;
}
else{
$(this).removeClass(sclass);
ftime = false;
}
}
});
}
};
})(jQuery);
$(document).ready(function() {
$.fn.dir_auto();
});
//css
body{
direction: rtl;
}
.inputs-nyn.auto-nyn05[dir="auto"] {
direction: rtl;
}
.inputs-nyn[dir="auto"]::placeholder {
text-align: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- HTML -->
<input class="inputs-nyn auto-nyn05" dir="auto" placeholder="متن فارسی..." type="text">
You cannot do that with HTML markup, since the dir attribute sets the basic directionality of all attributes of the element (and the element content, if it has content).
What you can do is to override the basic directionality for an attribute at the character level. This means that you set the element’s directionality to LTR (so that the value will appear that way) but use U+202B RIGHT-TO-LEFT EMBEDDING at the start of the placeholder value and U+202C POP DIRECTIONAL FORMATTING at its end. This will make it an “RTL island”. E.g.,
<input ... dir=ltr placeholder="‫...‬">
Unfortunately, the placeholder text will then appear as left-aligned (due to the element’s directionality). But the directionality of that text will be RTL.

CSS selector in the URL

When you have a url like this www.example.com/#signup, what the browser does is just to focus it's view on the HTML element with id signup, is that right?
Is it possible to change the element's CSS style if it's focused in that way?
E.g. let's say I have a div element, with the id signup, then if I enter www.example.com, the div's background is white and if I enter www.example.com/#signup it's yellow. Like "emphasizing" the sign up form. Is this at all possible?
:target { background-color: yellow; }
The :target psuedo-class does exactly this.
You can read the window.location.hash property when the page loads and apply the corresponding css classs. Something like:
<script type='text/javascript>
function init(){
var hash = window.location.hash.substr(1);
var element = document.getElementById(hash);
if(element){
element.className += " emphasize";
}
}
</script>
<body onload="init()">
...
</body>

Ideas for multicolored textbox?

In my site, I would like to implement a textbox where people can input a set of strings separated by a separator character.
For example the tags textbox at the bottom of this page: tags(strings) delimited by space(separator).
To make it more clear to the user, it would make a lot of sence to give each string a different background color or other visual hint.
I don't think this is possible with a regular input[text] control.
Do you deem it possible to create something like that with javascript? Has somebody done this before me already? Do you have any other suggestions?
Basic Steps
Put a textbox in a div and style it too hide it.
Make the div look like a text box.
In the onClick handler of the div, set the input focus to the hidden text box.
Handle the onKeyUp event of the hidden text box to capture text, format as necessary and alter the innerHtml of the div.
Tis quite straightforward. I'll leave you to write your formatter but basically you'd just splitString on separator as per the Semi-Working-Example.
Simple Outline
<html>
<head>
<script language="javascript" type="text/javascript">
function focusHiddenInput()
{
var txt = document.getElementById("txtHidden");
txt.focus();
}
function formatInputAndDumpToDiv()
{
alert('Up to you how to format');
}
</script>
</head>
<body>
<div onclick="focusHiddenInput();">
Some label here followed by a divved textbox:
<input id="txtHidden" style="width:0px;" onKeyPress="formatInputAndDumpToDiv()" type="text">
</div>
</body>
</html>
Semi-Working Example
You still need to extend the click handlers to account for tag deletion/editing/backspacing/etc via keyboard.... or you could just use a click event to pop up another context menu div. But with tags and spacer ids identified in the code below that should be pretty easy:
<html>
<head>
<script language="javascript" type="text/javascript">
var myTags=null;
function init()
{
document.getElementById("txtHidden").onkeyup= runFormatter;
}
function focusHiddenInput()
{
document.getElementById("txtHidden").focus();
}
function runFormatter()
{
var txt = document.getElementById("txtHidden");
var txtdiv = document.getElementById("txtBoxDiv");
txtdiv.innerHTML = "";
formatText(txt.value, txtdiv);
}
function formatText(tagText, divTextBox)
{
var tagString="";
var newTag;
var newSpace;
myTags = tagText.split(' ');
for(i=0;i<myTags.length;i++) {
newTag = document.createElement("span");
newTag.setAttribute("id", "tagId_" + i);
newTag.setAttribute("title", myTags[i]);
newTag.setAttribute("innerText", myTags[i]);
if ((i % 2)==0) {
newTag.style.backgroundColor='#eee999';
}
else
{
newTag.style.backgroundColor='#ccceee';
}
divTextBox.appendChild(newTag);
newTag.onclick = function(){tagClickedHandler(this);}
newSpace = document.createElement("span");
newSpace.setAttribute("id", "spId_" + i);
newSpace.setAttribute("innerText", " ");
divTextBox.appendChild(newSpace);
newSpace.onclick = function(){spaceClickedHandler(this);}
}
}
function tagClickedHandler(tag)
{
alert('You clicked a tag:' + tag.title);
}
function spaceClickedHandler(spacer)
{
alert('You clicked a spacer');
}
window.onload=init;
</script>
</head>
<body>
<div id="txtBoxDivContainer">
Enter tags below (Click and Type):<div id="txtBoxDiv" style="border: solid 1px #cccccc; height:20px;width:400px;" onclick="focusHiddenInput();"></div>
<input id="txtHidden" style="width:0px;" type="text">
</div>
</body>
</html>
Cursor
You could CSS the cursor using blink (check support) or otherwise just advance and hide as necessary an animated gif.
This is quite interesting. The short answer to your question is no. Not with the basic input element.
The real answer is: Maybe with some trickery with javascript.
Apparently Facebook does something close to this. When you write a new message to multiple persons in Facebook, you can type their names this sort of way. Each recognized new name is added a bit like an tag here and has an small cross next to it for removing it.
What they seem to do, is fake the input area size by drawing an input-looking box and removing all styling from the actual input with css. Then they have plenty of logic done with javascript so that if you have added an friend as a tag and start backspacing, it will remove the whole friends name at once. etc.
So, yes, it's doable, but takes plenty of effort and adds accessibility problems.
You can look how they do that at scripts like TinyMCE, which add such features to textareas. In textareas you can use HTML to colorize text.
You can use multiple textboxes
textbox1 <space> textbox2 <space> textbox3 ....
and so on... You can then apply the background-color style to each textbox.