How to cancel selection in contenteditable div? - javascript

On my page, I have a contenteditable div element. When a specific key is pressed, a function executes:
function bla(element) {
if (getSelectionHtml() != "") {
replaceSelectedText("text");
}
}
getSelectionHtml() checks if something is selected by the user. replaceSelectedText(text) replaces the selected text with a given string. Both functions are working properly.
After the selected text has been replaced, I want to 'cancel' the user's selection, as the selection is now equal to the 'new' string, so just deleting the text is not an option.
I tried this:
element.style.userSelect = "none";
element.style.userSelect = "text;
But it didn't work because userSelect: none doesn't seem to change anything in a div element with contenteditable. Also, this solution looks pretty ugly for such a simple problem.
So, how can I cancel the user's selection?

I think you want to remove selection completely. You can do so once you have replaced the string with
window.getSelection().removeAllRanges()
So basically, once you select the range of content, you can get the range with window.getSelection() method which returns set of details about selected content. It has many functions to alter the range and remove the range completely. To know more, you can read in brief of all supported methods Selection API

Related

How can I detect when a user has selected an option from a datalist?

I want to be able to detect when a user has selected an option from the dropdown box on an input element linked to a datalist so that I may use that action to trigger another.
For some reason, clicking on the datalist dropdown box does not fire a click event. So using that is totally out of the question.
Using the change event doesn't work for two reasons. Chrome's change event is pretty nice, it will fire when someone selects an option, however, in Firefox the event is not fired until the input has lost focus. You may think that you could at least use the change event for Chrome, but alas, there is another major issue—if you type in the full text of what you're selecting and then click an option, the change event is never fired, because nothing changed :(
Finally, we come to the very ugly but seemingly only option: comparing the current value of the input element to the options in the datalist with an input event. This has many issues.
It doesn't work if one option is a prefix of another (e.g. foo, foobar). The code will run prematurely if the user types foo before selecting foobar.
Assuming none of your options are prefixes of each other, your code will still run if the user types out the whole text of something in the datalist, as opposed to waiting for them to select it.
It has to loop through every single option in the datalist every time you
type a character.
You could try to mitigate these issues using setTimeout to detect when someone has stopped typing, but that still wouldn't be able to achieve the desired behaviour.
I can't believe there's not a simple event that deals with this, but I know there must be a way.
Indeed, there is a way! Our hero is the Invisible Separator (U+2063). It is a character that adds no visible effect to a string, it merely exists. Copy and paste this f⁣oo and check its length. You will see it equals 4!
We can append this character to the end of every option in the datalist. Then we can set up a listener for an input event, and check if the value of the input element ends in U+2063. If it does, you know the user has selected an option. You then should change the value of the input element to get rid of the U+2063 (unless the selection is going to trigger something that resets the value anyway).
This overcomes every issue you've stated because the user can't actually type in anything that matches something in the datalist, an option must be selected for anything to happen.
document.querySelector('input').addEventListener('input', function(){
if (this.value.slice(-1) === '\u2063') {
this.value = this.value.slice(0, -1);
let div = document.querySelector('div');
div.textContent = `you selected: ${this.value}`
div.classList.toggle('red'); //so you can see when this is called even if the text doesn't change
}
});
body {
display: flex;
}
div {
margin-left: 1em;
}
.red {
color: red;
}
<input list='test'>
<datalist id='test'>
<option>foo⁣</option>
<option>bar⁣</option>
<option>foobar⁣</option>
</datalist>
<div></div>

How to see if user selection is within an HTML span

I am working on a Firefox add-on that converts onscreen temperatures that the use highlights via the user selection. Once it is converted the user selection is replaced with a span HTML element with the ID of alreadyconverted that contains the original temperature and the converted temperature in brackets. An obvious glitch in the code is that the user can then go through and select the converted temperature and infinitely convert it.
What I want is for my Javascript code to detect when the user selection is contained within the span element, overlapping the span element or contains the entire span element. How can I have Javascript detect when the user has selected that span in full or in part?
I saw a similar question on StackOverflow, but it wanted to know when the user selection was contained entirely within the certain element. That's not completely what I want, but I'm not sure what I would need to change in the code to make it suit my needs.
View the JS Fiddle for that thread: http://jsfiddle.net/eT8NQ/
Looking at MDN's documentation for Select, it appears this functionality is already directly supported. See Selection.containsNode().
I've updated your fiddle, and now it properly returns a boolean whether any portion of the element is in your selection.
function elementContainsSelection(el) {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount > 0) {
return sel.containsNode(el, true);
}
}
return false;
}
This function is defaulted to return false unless the aPartlyContained flag is set. Then partial containment will also return true.
aPartlyContained
When true, containsNode() returns true when a part of
the node is part of the selection.
When false, containsNode() only
returns true when the entire node is part of the selection.

Unexpected JS behavior when clearing input field value - STCombobox

I am using some JQuery Combobox that you can check out here: https://simpletutorials.com/uploads/1860/demo/index.html
As you can see, you can start typing and get the results filtered.
However, once you have selected a value, when clicking on the arrow to open the list, no other values are shown anymore. So, if I want to change college/state, I need to manually clear the input value. I don't like this, so I want to modify it.
I changed that code and added this JS on the click event of the list:
onclick="document.getElementById('statesCombo-ddi').value='';"
This line basically finds the input by id and sets its value to an empty string.
You can try out by looking for the td element having class "stc-button" (with Chrome, just focus on the arrow of the second combo box) and add my code to the tag.
===EDIT===
You can obtain the same results by adding this code directly to the input:
onclick="this.value=''"
===END EDIT===
This has a weird behavior:
If I SELECT an element from the list, it clears the value and everything works correctly.
If I TYPE some letters and then select a value from the list, no item is shown in the list after clicking.
What's wrong with it?
You can override one of the combo box methods to accomplish this:
STComboBox.prototype.filterAndResetSelected = function() {
this.$('ddi').val('');
this.filterList('');
this.selectRow(0);
this.$('ddl').scrollTop(0);
};
Does this help?
The unminified code is provided, is relatively small (12kb) and is fairly well commented, so you could make this modification directly to the source if you'd like.
Edit: Fixed to clear the input value (as indicated in the comment below)
By reading the source and doing a little debugging with Chrome's inspector (Control+Shift+i), you can find the particular ID of the element you need to clear (#collegesCombo-ddi) in order to clear the input box. Once you've found the element's ID you need to clear (and being very careful with plugins that assign multiple elements with the same ID, which is not allowed in the standard, and an indicator of poorly-written code):
$('#collegesCombo-ddi').val('');

HTML textarea prevent some text from being deleted

I am making a terminal window in HTML/JavaScript and am using a textarea for input. I would like to prevent sections of the text in the textarea from being deleted. For example, if I had the text in the textarea "C:\>Random Code" I would like to prevent the user deleting the "C:\>" text. Is this possible using javascript?
Assuming jQuery, this script will listen for keystrokes, and if any of the required text can't be found (ie: user tries to delete it) it will add itself right back in there:
var requiredText = 'C:>';
$('textarea').on('input',function() {
if (String($(this).val()).indexOf(requiredText) == -1) {
$(this).val(requiredText);
}
}
You cannot make a section of textarea uneditable (only the whole control).
You can use various JavaScript trickery (listening to keypress events and cancelling event using event.preventDefault if the user wants to do something that you do not want to allow)
Another solution is to, instead of having an undeletable section of the input, to automatically append (or prepend ) a predefined string to the user input (and conveneintly display it for the user in some way).
Update:
So, my solution would look like this:
var requiredText = 'C:>';
$('textarea').on('keyup',function(event) {
if (GetSelectionStart(this) < requiredText.length){
event.preventDefault();
event.stopPropagation();
}
}
Where GetSelectionStart is a function that tells the beginning of the selected text (or caret position, if no text range is selected). For some possible implementations, see e. g. Caret position in textarea, in characters from the start
This function assumes that requiredText is always at the beginning of the string. But of course, it can be adapted for more complex scenarios.

Switchable selectable text

I have a table which is filled with data from a database. Some javascript allows a user to select certain rows and take some actions. I allow users to click one row and then to shift click another row to create a group (as well as alt-click to select/deselect individual rows).
The problem is I don't like how the text highlights when they shift click. Is there some CSS setting or javascript/jQuery solution to disable the selectable text (cross browser preferablly or just in firefox).
If possible I also want to be able to let the user select text to copy and paste sometimes or inside a textbox form input inside the same table so I would like to be able to enable and disable the selecting of text somehow. Any ideas?
this should do the trick:
$('td').disableSelection();
example:
http://jsfiddle.net/GhfuJ/1/
Here's one way you could completely disable text selection:
$("selector").bind($.support.selectstart ? "selectstart" : "mousedown", function(event) {
event.preventDefault();
});
This is how jQueryUI implements its disableSelection() method.
You could tailor your selector to exclude textarea elements, or wrap code inside the event handler with an if block that evaluates a boolean that gets set under certain circumstances (For example, you could turn on booleans when the user is clicking or shift/alt + clicking).

Categories

Resources