How to prevent a user from removing <section> inside <div contenteditable> editor during editing (at least by pressing "Delete"/"Backspace" keys)?
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
#editor {
width: 100%;
height: 300px;
border: 1px black solid;
}
#dont-remove-me-please{
width: 100%;
height: 100px;
border: 1px red dashed;
font-weight: bold;
user-select: none;
}
</style>
</head>
<body>
<div id="app"></div>
<div contenteditable="true" id="editor">
<div>hey guys!</div>
<div><strong>more text...</strong></div>
<section id="dont-remove-me-please" contenteditable="false">DONT' REMOVE ME!!!</section>
<div><br></div>
</div>
<script>
document.getElementById('editor').focus()
</script>
</body>
</html>
Thank You.
You can set contenteditable=false to children to prevent them from being editable.
However if you still want the children to be editable but the child dom elements shouldn't be removable I think you need to listen to backspace/delete events and see how these effect the dom and undo the changes if they remove dom nodes. Trying to figure this out myself
Edit: this is what I did
function onpaste(e: ClipboardEvent) {
e.preventDefault();
const selection = window.getSelection();
// Don't allow deleting nodes
if (selection.anchorNode.isSameNode(selection.focusNode)) {
// get text representation of clipboard
const text = e.clipboardData.getData("text/plain");
// insert text manually, but without new line characters as can't support <br/>s yet
document.execCommand("insertHTML", false, text.replace(/\n/g, ""));
}
}
function onkeydownInEditable(e: KeyboardEvent) {
if (e.key === "Enter") {
e.preventDefault();
}
if (e.key === "Backspace" || e.key === "Delete" || e.key === "Paste") {
const selection = window.getSelection();
// Don't allow deleting nodes
if (!selection.anchorNode.isSameNode(selection.focusNode))
e.preventDefault();
}
}
elementEditing.addEventListener("keydown", onkeydownInEditable);
elementEditing.addEventListener("paste", onpaste);
To achieve expected result, use below click event listener and add contenteditable attribute based on id
<script>
document.getElementById('editor').addEventListener('click', function(e) {
if(e.target.id !=="dont-remove-me-please"){
e.target.setAttribute("contentEditable", true);
}
}, false);
</script>
code sample - https://codesandbox.io/s/rypy7wkn5m
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
#editor {
width: 100%;
height: 300px;
border: 1px black solid;
}
#dont-remove-me-please{
width: 100%;
height: 100px;
border: 1px red dashed;
font-weight: bold;
user-select: none;
}
</style>
</head>
<body>
<div id="app"></div>
<div id="editor">
<div>hey guys!</div>
<div><strong>more text...</strong></div>
<section id="dont-remove-me-please" contenteditable="false">DONT' REMOVE ME!!!</section>
<div><br></div>
</div>
<script>
document.getElementById('editor').focus()
</script>
<script>
document.getElementById('editor').addEventListener('click', function(e) {
if(e.target.id !=="dont-remove-me-please"){
e.target.setAttribute("contentEditable", true);
}
}, false);
</script>
</body>
</html>
Related
I am trying to get a div by id, and adding an event listener to that div, in my case i am trying to implement a simple mouseover event. I am trying to create a new div element and in that element add a new class called vehicles, after adding className vehicles i am trying to modify the style attribute of width to 100px, the code provided is only for practice purposes even if it does not make sense in real life.
const myDiv = document.getElementById("div-1");
myDiv.addEventListener("mouseover", function(event) {
const newDiv = document.createElement("div");
newDiv.classList.add('vehicles');
const vehicles = document.getElementsByClassName("vehicles")[0];
vehicles.setAttribute("style", "width: 100px");
});
#div-1 {
background-color: red;
color: yellow;
width: 20px;
}
.vehicles {
border: solid 2px black;
background-color: blue;
width: 20px;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>test</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="div-1">
<p>This is a test</p>
</div>
</body>
</html>
You need to append the new created elements and then it will work:
const myDiv = document.getElementById("div-1");
myDiv.addEventListener("mouseover", function(event) {
const newDiv = document.createElement("div");
newDiv.classList.add('vehicles');
myDiv.append(newDiv); // append the new created div
const vehicles = document.getElementsByClassName("vehicles")[0];
vehicles.setAttribute("style", "width: 100px");
});
#div-1 {
background-color: red;
color: yellow;
width: 20px;
}
.vehicles {
border: solid 2px black;
background-color: blue;
width: 20px;
}
<div id="div-1">
<p>This is a test</p>
</div>
EDIT (comments):
const myDiv = document.querySelector("#div-1"); // use the modern way to select element(s)
myDiv.addEventListener("mouseover", function(event) { // this is your original code
const newDiv = document.createElement("div"); // this is also your original code
newDiv.setAttribute("style", "width: 100px; background: black; height: 1em;"); // instead of adding class and manipulate it you can set the desired property via inline style
myDiv.append(newDiv); // append the new created div
});
#div-1 {
background-color: red;
color: yellow;
width: 20px;
}
<div id="div-1">
<p>This is a test</p>
</div>
You have just created a new element. You must add this element to the DOM tree.
For example,
document.body.appendChild(newDiv);
red circle will not disappear
Definition and Usage
The onclick event occurs when the user clicks on an element.
Technical Details
Bubbles: Yes
Cancelable: Yes
Event type: MouseEvent
Supported HTML tags: All HTML elements, EXCEPT: , , , , , , , , , , and
DOM Version: Level 2 Events
<head>
<title>Javascript</title>
<style type="text/css">
.circle {
width: 120px;
height: 120px;
border-radius:50%;
float:left;
margin-right:50px;
}
#red-circle {
background-color: red;
}
#blue-circle {
background-color: blue;
}
#yellow-circle {
background-color: yellow;
}
</style>
</head>
<body>
<div class="circle" id="red-circle"></div>
<div class="circle" id="blue-circle"></div>
<div class="circle" id="yellow-circle"></div>
<script type="text/javascript">
documnet.getElementById("red-circle").onclick = function() {
document.getElementById("red-circle").style.display = "none";
}
</script>
</body>
You have a typo:
documnet.getElementById("red-circle").onclick = function() {
documnet instead of document. Just run it and check console.
I am trying to make a simple widget that allows the user to select either the check box OR the whole div to change its value. I have the following code:
$(document).ready(function() {
$(document).on("click", ".inputCheck", function(event) {
event.stopImmediatePropagation();
event.preventDefault();
$(this).closest(".outter").trigger("click");
});
$(document).on("click", ".outter", function(event) {
console.log("inside");
event.stopImmediatePropagation();
event.preventDefault();
var $checkBox = $(this).find("input");
$(this).removeClass("selected");
$checkBox.prop("checked", !$checkBox.prop("checked"));
if ($checkBox.prop("checked"))
$(this).addClass("selected");
});
});
.outter {
width: 100px;
height: 100px;
border-style: solid;
border-width: 1px;
}
.outter:hover,
.inputCheck:hover {
cursor: pointer;
}
<!DOCTYPE HTML>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div class="outter">
<input class="inputCheck" type="checkbox">
<div>This is a test</div>
</div>
</body>
</html>
It works as normal when the div is selected I.e. Checkbox changing values and a new class 'selected' being added to the .outter class. When the checkbox is selected I try to stop all defaults and propagation and then trigger the same code as selecting the div to change the class value. However the check box stays the same. Can someone please tell me why this isn't working and how to fix it?
Thanks
You don't need to stop propagation or anything. You can just check if the click was on the input or not, then change the input checked status like following. The click on the input will automatically be propagated to the parent div. You can check the click origin using event.target and make necessary actions.
$(document).ready(function() {
$(".outter").click(function(event) {
console.log('clicked');
var $checkBox = $(this).find("input");
$(this).removeClass("selected");
if (!$(event.target).is($checkBox)) {
$checkBox.prop("checked", !$checkBox.prop("checked"));
}
if ($checkBox.prop("checked"))
$(this).addClass("selected");
event.stopPropagation();
});
});
.outter {
width: 100px;
height: 100px;
border-style: solid;
border-width: 1px;
}
.outter:hover,
.inputCheck:hover {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="outter">
<input class="inputCheck" type="checkbox" />
<div id="testIt">This is a test</div>
</div>
$(document).ready(function() {
$(document).on("click", ".inputCheck", function(event) {
event.stopImmediatePropagation();
$(this).closest(".outter").trigger("click");
});
$(document).on("click", ".outter", function(event) {
console.log("inside");
event.stopImmediatePropagation();
var $checkBox = $(this).find("input");
if ($checkBox.prop("checked"))
$(this).addClass("selected");
else
$(this).removeClass("selected");
});
});
.outter {
width: 100px;
height: 100px;
border-style: solid;
border-width: 1px;
}
.outter:hover,
.inputCheck:hover {
cursor: pointer;
}
<!DOCTYPE HTML>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div class="outter">
<input class="inputCheck" type="checkbox">
<div>This is a test</div>
</div>
</body>
</html>
I have a problem i'm working on, my program will highlight words if typed in an input field. It wont highlight words from both.(Example Input1 type "Test1", Input2 type "Test2") is there a way to keep the highlighted words active from one field when the user switches to another?
JSBIN: http://jsbin.com/xovisayaso/edit?html,css,js,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<title>JS Bin</title>
</head>
<body>
<div id="listArray">
<span>Test1</span>
<span>Test2</span>
<span>Test3</span>
</div>
<input type="text" class="form-control" id="userArray">
<input type="text" class="form-control" id="userArray2">
</body>
</html>
<script
$("#userArray, #userArray2").on('change keyup paste', function() {
var input = $(this).val().toLowerCase().split(" ");
$('#listArray span').each(function(){
$(this).removeClass('active');
if( $.inArray( $(this).text().toLowerCase(), input ) != -1 ) {
$(this).addClass('active');}});});
</script>
<style>#list_input > div { border:4px solid; padding: 1em; margin: 1em auto; }
#listArray { overflow: auto; }
#listArray span { display: block; float: left; clear: left; padding:4px; margin:1px; }
#listArray span.active { background: green; }
}
</style>
You can achieve the desired effect by removing the active class whenever the text changes and then checking against both inputs:
$("#userArray, #userArray2").on('change keyup paste', function() {
$('#listArray span').removeClass('active');
$('input').each(function() {
var input = $(this).val().toLowerCase().split(" ");
$('#listArray span').each(function() {
if ($.inArray($(this).text().toLowerCase(), input) != -1) {
$(this).addClass('active');
}
});
});
});
#list_input > div {
border: 4px solid;
padding: 1em;
margin: 1em auto;
}
#listArray {
overflow: auto;
}
#listArray span {
display: block;
float: left;
clear: left;
padding: 4px;
margin: 1px;
}
#listArray span.active {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="listArray">
<span>Test1</span>
<span>Test2</span>
<span>Test3</span>
</div>
<input type="text" class="form-control" id="userArray">
<input type="text" class="form-control" id="userArray2">
Try this code :
$("#userArray, #userArray2").on('change keyup paste', function() {
var input = $("input").map(function(){return $(this).val().toLowerCase();}).get();
$('#listArray span').each(function(){
if( $.inArray( $(this).text().toLowerCase(), input ) != -1 ) {
$(this).addClass('active');
}
else
$(this).removeClass('active');
});
});
Reason : In your code you are only getting single value at a time to compare, rather the both textbox's values !!!
I am building a simple Grocery List App and I am having issues trying to remove a place holder div element.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Grocery List App</title>
<link type="text/css" href="style/form.css" rel="stylesheet"/>
</head>
<body>
<div id="container">
<div id="left_side">
<div id="to_buy">To Buy:</div>
</div>
<div id="right_side">
<div id="in_cart">In Cart:</div>
</div>
</div>
<input type="text" id="item_body" placeholder="Type Item to Add">
<script src="scripts/jquery-1.11.2.min.js"></script>
<script src="scripts/grocery.js"></script>
<script src="scripts/jquery-ui/jquery-ui.js"></script>
</body>
</html>
JS
$(function () {
var rmv = false;
$('#item_body').keydown(function(e) {
if (e.keyCode == 13) {
var add = $('#item_body').val();
$("#to_buy").append('<div class="draggable_item">' + add + '</div>');
$("#in_cart").append('<div class="holder"></div>');
}
$(".draggable_item").draggable( {
axis: "x"
});
$(".draggable_item").dblclick(function() {
this.remove();
$('#in_cart > div:first').remove();
});
});
});
CSS
#to_buy {
float:left;
width: 50%;
height: 100%;
color: #00E5EE;
}
#in_cart {
float: left;
width: 49%;
height: 100%;
color: #00E5EE;
}
#container {
width:100%;
height: 100%;
}
#left_side {
height: 100%;
width: 50%;
float:left;
background: #5D5851;
}
#right_side {
height: 100%;
width: 50%;
float: left;
background: #6D5D4D;
}
#item_body {
float:left;
clear:both;
color: #326B62;
}
body {
background: #B1ADA5;
}
.draggable_item {
color: #FFF;
}
.holder {
height: 20px;
}
So the screen is split vertically between "to_buy" and "in_cart." When I add an item to "to_buy" I also add a "dummy" div to "in_cart" so that the two sides remain even. However, when I double click to remove an item, when
$('#in_cart > div:first').remove();
gets called, first one div is removed, then on the next double click two, then four etc etc. Apparently, it is getting called multiple times or something else wonky is going wrong.
This is because you bind event handlers for double click event on every Enter key press so they multiply on every item addition. Just move dblclick registration outside:
var rmv = false;
$('#item_body').keydown(function (e) {
if (e.keyCode == 13) {
var add = $('#item_body').val();
$("#to_buy").append('<div class="draggable_item">' + add + '</div>');
$("#in_cart").append('<div class="holder"></div>');
}
$(".draggable_item").draggable({
axis: "x"
});
});
$("#left_side").on("dblclick", ".draggable_item", function () {
this.remove();
$('#in_cart > div:first').remove();
});
Also note, that it makes sense to delegate double click event to the parent container #left_side so you don't have to worry about presence of elements at the time of event registration.
Here is a demo: http://jsfiddle.net/hx11gkcj/