Prevent contenteditable element from getting focus when clicking parent - html

When clicking anywhere above the "Outside" div container in the following example, the contenteditable span element gets the focus.
<div style="margin:30px">
<span contenteditable="true" style="background:#eee">
Hello World
</span>
<div>Outside</div>
</div>
Here's a jsFiddle:
http://jsfiddle.net/AXM4Y/
I want the contenteditable behave more like a real text input, thus only clicking the span element itself should trigger its focus. How do I do this? How can the event capturing of the container element be stopped. I've already tried "e.stopPropagation()" with jQuery on the parent div, but it didn't work.

I fixed it with the way I put pointer-events: none on parent element and pointer-events: all on element with content editable attribute.

There's quite a bit more to making a content editable behave like an input but in answer to your question, this works in Chrome 98 browser.
const myEditableContainer = document.querySelector('.my-editable__container');
const button = document.querySelector('button');
let disabled = false;
const buttonText = (disabled) => `Click to ${disabled ? 'enable' : 'disable'}`;
button.innerHTML = buttonText(disabled);
button.addEventListener('click', () => {
disabled = !disabled;
button.innerHTML = buttonText(disabled);
myEditableContainer.classList.toggle('my-editable-container--disabled', disabled);
});
.my-editable__container {
position: relative;
}
.my-editable__cover {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
pointer-events: none;
background-color: white;
}
.my-editable-container--disabled .my-editable__cover {
pointer-events: all;
opacity: 0.5;
}
<div style="margin:30px">
<div class="my-editable__container">
<span class="my-editable" contenteditable="true" style="background:#eee">
Hello World
</span>
<span class="my-editable__cover"></span>
</div>
<button>
Enable/Disable
</button>
<div>Outside</div>
</div>

Related

Why is my paragraph popup coming outside my div with the "mousedown" event?

I need to show my paragraph inside my <div> when click on the <div>. This is my code:
const area = document.getElementById("area");
const popup = document.getElementById("popup");
function showPopup(event) {
let x = event.clientX;
let y = event.clientY;
popup.style.left = `${x}px`;
popup.style.top = `${y}px`;
popup.style.visibility = "visible";
}
area.addEventListener("mousedown", showPopup);
.area {
border: 1px solid;
position: absolute;
height: 200px;
width: 200px;
}
.popup {
visibility: hidden;
position: absolute;
display: inline-block;
}
<div id="area" class="area">
<p class="popup" id="popup">popup</p>
</div>
Note that this is inside another main body <div> (also with position: absolute).
Try this
<div id="area">
<div class="area""
<p class="popup" id="popup">popup</p>
</div>
</div>
I tested your code and observed you are changing style.top property based on your ClientX value which is causing popup element to appear over random position. Use following updated code and it's should be good.
function showPopup(event) {
console.log(event.clientX, event.clientY)
let x = event.clientX;
let y = event.clientY;
popup.style.left = `${x - 8}px`;
popup.style.top = `${y - 8}px`;
popup.style.visibility = "visible";
}
and few CSS changes as -
.area {
border: 1px solid;
position: relative;
height: 200px;
width: 200px;
}
.popup {
visibility: hidden;
position: absolute;
display: inline-block;
margin: 0;
}
For more close positioning of popup element.

press a button to a css div block

I am working on a website.
I have a div block
<div id="table_and_dqinfo" class="table_and_dqinfo">
<div id="dqdiv" class="dqinfo">
<h4 class="centertext">Information Pane</h4>
<div id="dqdiv_volgraph"></div>
</div>
</div>
dqdiv_volgraph is an image block which has the image link.
Instead of putting the div block above into the CSS to show the image directly on the website, I want to put a CSS button, so that only after I press the button, it would open the div block above to show the image on the website.
Could anyone give me some hints about how to do it?
Is this what u want?
I used checkbox and label as a button.
When you click on label, it checks the checkbox, then using sibling selector (+) of CSS
input:checked + #dqdiv_volgraph{
display:block;
}
I toggle the visibility of the #dqdiv_volgraph div
Feel free to style the label tag and make it look like a button according to your project
Note that the for attrib of label and id of the input should
be same
input,
#dqdiv_volgraph {
display: none;
}
label {
border: 1px solid black;
padding: 5px;
cursor: pointer;
}
input:checked+#dqdiv_volgraph {
display: block;
}
<div id="table_and_dqinfo" class="table_and_dqinfo">
<div id="dqdiv" class="dqinfo">
<h4 class="centertext">Information Pane</h4>
<input id="checkb" type="checkbox">
<div id="dqdiv_volgraph">
<h1>Put image here</h1>
<img src="https://placehold.it/200x200">
</div>
<label for="checkb"> Click me</label>
</div>
</div>
Alternatively, you could also use JavaScript to solve this particular issue.
function showImage(n) {
var Images = document.getElementsByClassName("table_and_dqinfo");
//Get all elements with class "table_and_dqinfo"
var i = 0;
if (Images[n].style.display == "block") {
Images[n].style.display = "none";
return;
}
//Checks to see if the selected Image is already visible. If so it
//switches it makes it invisible
for (i = 0; i < Images.length; i++) {
Images[i].style.display = "none";
}
//Make the other Images invisible.
Images[n].style.display = "block";
//Change selected Image to visible
}
function showAll() {
var Images = document.getElementsByClassName("table_and_dqinfo");
var i = 0;
for(i = 0; i < Images.length; i++) {
if (Images[i].style.display == "block") {
Images[i].style.display = "none";
continue;
}
Images[i].style.display = "block";
}
}
.table_and_dqinfo {
display: none;
background-color: blue;
color: white;
}
.button {
border: 1px solid black;
cursor: pointer;
margin: 20px;
}
<span class="button" onclick="showImage(0)"> Button for Image 1 </span>
<span class="button" onclick="showImage(1)"> Button for Image 2 </span>
<span class="button" onclick="showAll()"> Button to show all Images </span>
<div class="table_and_dqinfo">
<div>
<h4>Image 1</h4>
<div></div>
</div>
</div>
<div class="table_and_dqinfo">
<div>
<h4>Image 2</h4>
<div></div>
</div>
</div>
Style the button as you please. You can also put whatever you want inside the <div class="table_and_dqinfo">

CSS - Have Image Move With Centered Text-Align Input Text

I have an text input with the following HTML:
<span>
✍
</span>
<input type="text">
and the corresponding CSS:
input{
text-align: center;
border: none;
outline: none;
background-color: transparent;
}
The input element should blend seamlessly into its background with only the HTML icon indicating that it is indeed an input. The HTML icon will remain in a static position with the current mark-up as new text is added into the input.
Is there anyway to have my HTML icon start right to the left of the first letter and have it gradually move toward the left as the left boundary of the text string pushes in the same direction?
Fiddle Example
If you're ok with contenteditable you could try this:
span{
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
span::before {
content: '\270D';
}
<span contenteditable='true'></span>
A possible but imperfect (needs lots of work) idea using jquery.
fiddle
$('input').bind('keypress', function(e) {
var tester = $(this).val().length;
var code = e.keyCode || e.which;
var currentWidth = $('input').css('width').slice(0, -2);
var currentWidthParsed = parseInt(currentWidth, 10);
if(code == 8) {
var newWidth = (currentWidthParsed - 8) + 'px'
$('input').css('width', newWidth);
} else {
var newWidth = (currentWidthParsed + 8) + 'px'
$('input').css('width', newWidth);
}
});
body {
text-align: center;
}
input{
text-align: left;
border: none;
outline: none;
background-color: transparent;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<span>
✍
</span>
<input type="text">
As far as I know you can't have dynamic width of inputs with something like width: auto. In that case you could have a wrapper with fixed with and a text-align right.
So I would say the only possibility is to have that icon inside the value of the input (if it may exist as UTF-8 icon) and then strip it out when processing the value. But of course this would seem dirty.

Hover over words in a text

What would be the best way to display a hover popup with a 20-30 words definition of each word in a foreign-language text?
Right now I am using an iframe:
<span class="tooltip">foreign-language-verb
<span class="tooltiptext">
2nd pers. sing. past tense, active mood.
<iframe class="tooltip" src="general_dictionary_definition_of_the_verb.html"></iframe>
</span>
</span>
It works but the page is then very slow to load and there seems to be a limit to the number of possible iframe's: they don't display anymore if the text is too long.
Any other solution, using javascript to load the text or something?
Thanks.
EDIT:
Following up on Richard P's remark: does that mean replacing iframe with javascript loading by hand, does that make sense, is that best practices? Would that be faster than the iframe's which are very slow to load?
Taking Javascript - read local text file into account:
<script type="text/javascript">
function loadDictionaryDefinitions()
{
var elements = document.getElementsByClassName("DictionaryDefinition");
for (var i = 0; i < elements.length; i++)
elements[i].innerHTML = readTextFile("file://" + elements[i].getAttribute("filename_of_dic_definition"));
}
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
}
rawFile.send(null);
}
</script>
and add:
<body onload="loadDictionaryDefinitions()">
what about css hover ? Try this one:
https://jsfiddle.net/maky/0h0ekhj6/
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
/* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
/* Position the tooltip text - see examples below! */
position: absolute;
z-index: 1;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
You could use a popover in Bootstrap if you don't mind adding it to your project. It would require a bit of javascript but should be pretty simple. Most of the functionality of it is handled by Bootstrap.

HTML5/Cesium - making divs float over cesium map

I am using cesium : http://cesiumjs.org/
and I wanted to make some divs float over a cesium map, but I can't get it to work.
I tried the following container/tag method at jsfiddle.net/j08691/dChUR/5/ - substituing the image by a cesium map div - but it doesn't seem to work - the "tag" div isn't shown.
Any help?
You need to add position: absolute; and either top or bottom to your CSS, because the widget also uses absolute positioning. Adding this creates a new stacking context, which overrides z-index.
Here's a working example, hit "Run Code Snippet" at the bottom of this:
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
var viewer = new Cesium.Viewer('cesiumContainer', {
timeline: false,
animation: false,
navigationHelpButton: false
});
var skyAtmosphere = viewer.scene.skyAtmosphere;
var skyCheckbox = document.getElementById('skyCheckbox');
skyCheckbox.addEventListener('change', function() {
viewer.scene.skyAtmosphere = skyCheckbox.checked ? skyAtmosphere : undefined;
}, false);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif; color: #edffff;
}
#controlPanel {
position: absolute;
top: 5px;
left: 5px;
background: rgba(42, 42, 42, 0.8);
padding: 5px 8px;
border-radius: 5px;
}
label {
cursor: pointer;
}
label:hover span {
text-decoration: underline;
}
<link href="http://cesiumjs.org/releases/1.15/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.15/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
<div id="controlPanel">
This is a floating control panel<br/>
with a translucent background color.
<p>
<label>
<input id="skyCheckbox" type="checkbox" checked />
<span>Enable atmospheric effect</span>
</label><br/>
<button class="cesium-button">Button 1</button>
<button class="cesium-button">Button 2</button>
</p>
</div>
To add to emackey's answer, what I had to do in addition to adding position: absolute to my css was to add a top:150px or bottom:150px. Basically anything that will specify a position relative to the parent container.
Even though using the absolute position it is most likely being pushed down by the cesium widget since it takes up 100% height.