contenteditable on doubleclick - javascript

I've got a p tag with some text, and I'm trying to make it contenteditable but only on doubleclick. How can I prevent browser from placing the cursor on the p when I click on it and only do it when I doubleclick? JQuery:
p.dblclick(function(e){
p.css("cursor", "text");
})
.focusout(function(){
p.css("cursor", "default");
})
.click(function(e){
console.log('focus p');
e.stopPropagation();
$("body").focus(); // not stopping Chrome from placing cursor
});
I could make contenteditable false by default and then make it true on dbleclick and then do p.focus() but it means I can't place cursor where I clicked. On the other hand, I could make it contenteditable after first click and then wait like 1.5s for a dobuleclick and if it didn't happen cancel it, but if it happened, then the content would be editable and the second click would trigger the placement of the cursor in the right place. However, it's not that smooth and makes the content editable for these 1 and a half seconds.
Any ideas?
answer:
In case somebody is interested, I went on to implement the timer method, because I don't think there's any other way... here's the code
var DELAY = 700, clicks = 0, timer = null;
p.focusout(function(){
p.css("cursor", "default");
p.prop("contenteditable", false);
})
.click(function(e){
clicks++;
p.prop("contenteditable", true);
if(clicks == 1){
timer = setTimeout(function() {
p.prop("contenteditable", false);
//alert("Single Click"); //perform single-click action
clicks = 0; //after action performed, reset counter
}, DELAY);
} else {
clearTimeout(timer); //prevent single-click action
// alert("Double Click"); //perform double-click action
clicks = 0; //after action performed, reset counter
}
});

try this here a working fiddle
<p ondblclick="this.contentEditable=true;this.className='inEdit';" onblur="this.contentEditable=false;this.className='';" contenteditable="false" class="">This paragraph uses some simple script to be editable. Double-click the text to begin editing.</p>

Here is a solution which works for me:
<script>
function listenForDoubleClick(element) {
element.contentEditable = true;
setTimeout(function() {
if (document.activeElement !== element) {
element.contentEditable = false;
}
}, 300);
}
</script>
<p onclick="listenForDoubleClick(this);" onblur="this.contentEditable=false;">Double-click the text to begin editing.</p>
Here is a working fiddle: https://jsfiddle.net/dtL3xzfb/
It uses a timeout event to check if the text has been selected within a certain period of time (300ms), if the text is not selected (by a second click) it will set content editable to false again: The content editable parameter is set to true after the first click so text will be selected when you click for a second time.

You could make the text unselectable as in How to disable text selection using jQuery? :
var p = $('p');
p.attr('unselectable', 'on')
.css('user-select', 'none')
.on('selectstart', false);
p.dblclick(function (e) {
p.css("cursor", "text")
.attr('contenteditable', true)
.attr('unselectable', 'off')
.css('user-select', 'inherit')
.off('selectstart', false)
.focus();
});
p.focusout(function () {
p.css("cursor", "default")
.attr('unselectable', 'on')
.attr('contenteditable', false)
.css('user-select', 'none')
.on('selectstart', false);
});

If using React you may use the component
import _ from 'lodash'
import { useState } from 'react'
const inputValue = (e: any): string => e.target.value
function isEnterOrEscapeKeyEvent(event: React.KeyboardEvent<HTMLInputElement>) {
return event.key === 'Enter' || event.key === 'Escape'
}
const EditOnDblClick = () => {
const [isEditing, setisEditing] = useState(false)
const [text, settext] = useState('yoga chitta')
const onEditEnd = () => {
setisEditing(false)
}
return isEditing ? (
<input
value={text}
className="bg-transparent border-2 border-black border-solid"
onKeyDown={(event) => {
if (isEnterOrEscapeKeyEvent(event)) {
event.preventDefault()
event.stopPropagation()
onEditEnd()
}
}}
onChange={_.flow(inputValue, settext)}
onBlur={onEditEnd}
autoFocus
/>
) : (
<div className="select-none" onDoubleClick={() => setisEditing(true)}>
{text}
</div>
)
}
export default EditOnDblClick
Note: Classes are from tailwindcss

Related

Input is not cleared when working with e.target

I can't figure out what's going on. Below is the JS code that is responsible for closing and opening the search box running in the JS application. Closing occurs by pressing a button with a cross, Esc keyboard and anywhere in this window
const btn = document.querySelector('.head__search-icon'),
body = document.body,
search = document.querySelector('.search'),
searchInner = document.querySelector('.search__inner'),
searchOverlay = document.querySelector('.search__overlay'),
searchInput = document.querySelector('#search__input'),
btnClose = document.querySelector('.search__closed-button');
body.classList.add('no-search'),
search.style.display = 'none';
function searchOpen() {
btn.addEventListener('click', () => {
body.classList.remove('no-search');
body.classList.add('is-search');
search.style.display = 'block';
setTimeout(() => searchInput.focus(), 100);
if (body.classList.contains('is-head-open')) {
body.classList.remove('is-head-open');
}
});
}
searchOpen();
function searchClose() {
body.classList.add('no-search');
body.classList.remove('is-search');
searchInput.value = '';
searchInput.blur();
}
function searchRemove(e) {
if(e.code === "Escape" && body.classList.contains('is-search') || e.target === searchOverlay || e.target === searchInner) {
searchClose();
}
}
document.addEventListener('keydown', searchRemove);
search.addEventListener('click', searchRemove);
btnClose.addEventListener('click', searchClose);
The fact is that if there is a search result, and press Esc, then everything works, the focus from the input disappears, and the input itself is cleared. But if you click anywhere in the window ( e.target === searchOverlay || e.target === searchInner ), then the window itself closes, the input is cleared, as I need, except that with a visually clean input, the search results remain. That is, you open the window again and see the same search results, although the input is empty. When working with Esc, the input is actually cleared. Where is the jamb in the script?
In general, I made it easier, added a construction to the searchClose() function to remove the search result using innerHTML = ' '

Event handling function

In the task, you need to change the background colour of the block to green when you press the G key, but no changes are made.
<body>
<div id="colorOutput">
</div>
<script>
let div = document.querySelector("#colorOutput");
document.addEventListener("keydown", function (event) {
if (event.code == "Enter") changeToGreen();
})
function changeToGreen() {
div.style.backgroundСolor = "green";
}
</script>
Try using the below JS code.
const div = document.getElementById("colorOutput");
window.addEventListener("keydown", (e)=>{
e.code === "Enter" ? changeToGreen() : null;
});
function changeToGreen() {
alert("JAI HARI");
div.style.backgroundСolor = "green";
}
Use window instead of document for Event Listener.

How to know if we are leaving web page?

I have a form on my page. If it is changed because beforeunload event the user will have a dialog which catch the leave process.
If the user click on "continue" or "leave" then the new page is loading and form's data are lost.
If the user click on "cancel" the leave process is canceled.
How can we know when the user has clicked on cancel ?
Why I need to know that ?
In my case I have a switch button. When the user turns it on, the script tries to reload the page. If the user click on "continue" or "leave" it's ok. But if the user click on "cancel" I would like show back the switch on the position "off".
When a user changes the button position ON and then attempts to leave but then cancel, the state of the button should change to OFF. We can use window.onbeforeunload function and returning false within the block of its code. Please see the below example, note that I have used checkbox instead of toggle switch, but you can type anything inside the window.onbeforeunload function to your desire.
window.onbeforeunload = () => {
document.getElementById("checkbox").checked = false;
return false;
}
.checkbox {
margin-top: 20px;
margin-left: 20px;
}
<p>Clicking the link below should prompt with "Leave" or "Cancel" option. If you check the box, then click on the link, and then click on "Cancel", the checkbox should return to false.</p>
<div>
Click here to exit this site and go to google.com
</div>
<div class="checkbox">
<input type="checkbox" id="checkbox">
</div>
To handle the state of the button, we can use localStorage and setInterval timer to check if the user has left the site and onbeforeunload event to prompt user to leave or cancel. When user cancels, the interval counts down to 0, this means the user is still on your site and updates the localStorage, but if left, the interval will not continue and doesn't change the localStorage value, and therefore, when returning to your site, the checked button should be updated to the previous position. Note that, when you click Run code snippet on this site, it might not work for localStorage, run this code from your site or on JSFiddle. :-)
window.onload = () => {
// declaration & Initialization
const input = document.createElement("input");
const defaultCounterValue = 10; // incremental --
const defaultIntervalValue = 50; // ms
const checkbox = document.getElementById('checkbox');
const setLocalStorage = (itemName, itemValue) => {
localStorage.setItem(itemName, itemValue);
};
const getLocalStorage = (itemName) => {
return localStorage.getItem(itemName) === null ? false : localStorage.getItem(itemName) === 'false' ? false : true;
};
let interval = undefined;
let counter = defaultCounterValue;
setLocalStorage('checkbox', getLocalStorage('checkbox').toString());
setTimeout(() => {
checkbox.checked = getLocalStorage('checkbox');
}, 0);
checkbox.addEventListener('click', () => {
setLocalStorage('checkbox', checkbox.checked);
});
// set input property and event handlers
input.type = 'checkbox';
input.checked = false;
input.style.display = 'none';
input.addEventListener('click', () => {
let removeInterval = () => {
clearInterval(interval);
interval = undefined;
}
if (interval) {
removeInterval();
}
interval = setInterval(() => {
if (input.checked === true) {
if (counter === 0) {
checkbox.checked = false;
setLocalStorage('checkbox', checkbox.checked);
counter = defaultCounterValue;
input.checked = false;
}
counter--;
} else {
removeInterval();
}
}, defaultIntervalValue);
});
document.body.appendChild(input);
// Event that run before the user leaves
window.onbeforeunload = (event) => {
event.preventDefault = true;
event.cancelBubble = true;
event.returnValue = null;
input.checked = false;
input.click();
};
}
.checkbox {
margin-top: 20px;
margin-left: 20px;
}
<p>Clicking the link below should prompt with "Leave" or "Cancel" option. If you check the box, then click on the link, and then click on "Cancel", the checkbox should return to false.</p>
<div>
Click here to exit this site and go to google.com
</div>
<div class="checkbox">
<input type="checkbox" id="checkbox">
</div>

Display Content only if a user "wins"

having a bit of trouble.
im trying to creat a play again button the appears only when the user wins,
i've set the condition of the div to visibility:none when the user won,
else its in display:none
however, the button always appears, right from the start, any advice?
the audio plays correctly, only when the user wins.
so i got this piece of code in html:
<div id="Again">
<button type="button" onclick="toggle_visibility">Play Again</button>
</div>
and the following in js:
function toggle_visibility(id) {
var x = document.getElementById('Again');
if (TOTAL_COUPLES_COUNT === flippedCouplesCount) {
audioWin.play();
x.style.display = 'block';}
else {
x.style.display = 'none';
}
The initial display state of the button should be none. Here's a skeleton snippet that may help you along:
const button = document.querySelector("button");
const input = document.querySelector("input");
const inputHandler = evt => {
if (+evt.target.value == guessValue) {
button.classList.replace("hidden", "visible");
} else {
button.classList.replace("visible", "hidden");
}
};
let guessValue = Math.ceil(Math.random() * 10);
button.addEventListener("click", () => {
button.classList.replace("visible", "hidden");
input.value = "";
guessValue = Math.ceil(Math.random() * 10);
});
input.addEventListener("change", inputHandler);
input.addEventListener("keyup", inputHandler);
button.hidden {
display: none
}
button.visible {
display: inline-block
}
<input type="number" max="10" min="1"> Guess a number (1 - 10)
<button class="hidden">Again?</button>
The button is visible since the beginning because it has neither an "hardcoded" style attribute which says to hide it or a CSS proprerty which does the same. The JS code which "toggles" the button is only triggered when pressed, so it has no effect as the page loads.

How to highlight double-clicked word in input after input.select()

There is an input with some text. All text in this input has to be selected when input is focusing (first click on input) and specific word has to be selected when second click on input occurs.
I try to implement the same functionality that URL-bar in Chrome(Version 74.0.3729.131 (Official Build) (64-bit)) has.
Current behavior of input you can see here: https://jsfiddle.net/deaamod1s/rh5mw0e4/23/
The only solution I see it's to check was the input double-clicked or not and after that if input wasn't double-clicked - to do input.select()
input.onfocus = function(e) {
let hasValueWhenGotFocused = false;
if (input.value) {
hasValueWhenGotFocused = true;
}
setTimeout(() => {
if (hasValueWhenGotFocused && this.className.indexOf("doubleclicked") == -1) {
this.select();
} else {
this.classList.remove("doubleclicked");
}
},400);
}
input.ondblclick = function(e){
this.classList.add('doubleclicked');
}
The onfocus event handler is always executed before the ondblclick.
I suggest to delay the focus handler so that it can be executed after a possible double click (updated fiddle here):
input.ondblclick = function (e) {
// set....
this.dataset.dblclick = true;
}
input.onfocus = function (e) {
this.dataset.dblclick = false;
setTimeout(function (_this) {
// if not set...
if (_this.dataset.dblclick == "false") {
_this.select();
} else {
// remove ...
delete _this.dataset.dblclick;
}
}, 200, this);
}
Try to select second word using only two click<br>
<input type="text" id="input" value="sdsas select_me">

Categories

Resources