Changing content of DOM text node - javascript

Say I have the following HTML:
<div>Some text</div>
I'm wanting to remove the last character from the text each time the user hits the backspace key. Is there a way to actually remove a character from a text node? Or do I have to do something like obj.innerText = 'Some tex' (i.e. trim the last char myself and replace the whole thing).

var div = document.getElementById('my-div');
document.addEventListener('keydown',
function(e) {
if (e.which === 8) {
div.textContent = div.textContent.substring(0, div.textContent.length - 1);
}
}, false);
You may also want to support IE8. In that case, use document.attachEvent() and div.innerText.

Best method I can think of off the top of my head is to use the substring method for Strings.
var s = obj.innerText
// Then On backspace event listener
s = s.substring(0, s.length - 1) // returns s without the last character in the original string.
obj.innerTezt(s) // set the inner HTML back to s
Edit: thanks Jonathan, Dennis for the correction on this answer!

// Get the element
var el = document.queryString("...")
// Get the text contents
var text = el.firstChild
if (text.nodeType === Node.TEXT_NODE) {
// Delete the last character
text.deleteData(text.length - 1, 1)
}
See the CharacterData DOM interface for details of deleteData

Related

How to get the -real- last character typed in input with maxlength?

I wanted to know which character the user is typing into an input:
I have an input:
<input maxlength="20"/>
and a script that returns the last typed char:
var eingabe;
$('form').on('keypress', function(event) {
/// if no whitespace:
if (String.fromCharCode(event.keyCode).replace(/\s/g, "").length > 0) {
eingabe = String.fromCharCode(event.keyCode);
$('#eingabe').html("<div>Eingabe : "+ eingabe +"</div>");
}
});
My question is:
because my input has a maxlength attribute, the last typed character on the keyboard is sometimes not the last -real- typed character into the input because the input is "full". How can I get the last character typed into the input?
I haven't tried it, but it must work...
Set onkeypress= or onkeydown= on the Input element and store the key value in a LastChr variable.
I had a similar problem. I wanted to call a function if the user types a specific character into my input field. I solved it with the following:
var input = document.getElementById('myInput');
input.addEventListener('input', function() {
// Get cursor position
var start = this.selectionStart;
// Get last typed character
var lastChar = String.fromCharCode(this.value.charCodeAt(start - 1));
if(lastChar === '[YOURCHARHERE]') {
// do something
}
});
Please keep in mind, that 'input' is only supported down to IE8, but if you don't care about a proprietary browser, you should be fine. I hope this helps.
Inside your function, use the value of the input element to get the last character like $('#input_field').val().substr($('#input_field').val().length - 1) or use your best coding skill to accomplish something similar without accessing the field twice, wink wink.
Use keyup instead:
$('form').on('keyup', function(event) {
var cursorPos = event.target.selectionStart;
var lastTypedChar = elem.target.value[cursorPos - 1];
});

Javascript prepend to line in textarea on double click

What I am trying to do:
Double click a line in a textarea.
Prevent text from being selected.
Prepend a dash to that line.
I know some basic jquery but can't seem to understand the lower level javascript that is required. Here is what I have so far:
$("textarea").dblclick(function() {
//TODO: Prevent selection
//TODO: Get the line number??
//TODO: prepend a dash to the line
// or replace the line with itself
// plus the dash at the front??
});
Here is the fiddle.
There may be a number of things you need to do, but something like this should be enough to get you started:
$("textarea").dblclick(function() {
//first, get the position of the cursor
var cursorPosition = $(this).prop("selectionStart");
//get the text value at the cursor position
var textValue = $(this).val().substr(cursorPosition,1);
//use a loop to look backward until we find the first newline character \n
while(textValue != '\n' && cursorPosition >= 0) {
cursorPosition--;
textValue = $(this).val().substr(cursorPosition,1);
}
//update the textarea, combining everything before the current position, a dash, and everything after the current position.
$(this).val(($(this).val().substr(0,cursorPosition+1) + '-' + $(this).val().substr(cursorPosition+1)))
});
You can see an example in this JS Fiddle:
http://jsfiddle.net/igor_9000/4zk5otvm/2/
There will probably be a lot more you need to add to this, depending on what you want to be able to do with the function and what limits you want to enforce, but that should be enough to get you started. Hope that helps!
I needed something similar, here's what you might've been looking for with vanilla JS (without jQuery or anything):
function dblClickEvt(obj) {
let pos = obj.selectionStart;
let text = obj.value;
let lineStart = text.lastIndexOf("\n", pos);
let lineEnd = text.indexOf("\n", pos);
let before = ( lineStart === -1 ? '' : text.slice(0, lineStart + 1) ); // row(s) before incl. line break
let after = '';
if(lineEnd === -1) // -> last row is selected
lineEnd = undefined; // because -1 would cause the selection to strip the last character
else
after = text.slice(lineEnd); // row(s) after the selection
let selected = text.slice(lineStart + 1, lineEnd); // the selected row
// write new value (manipulate before, selection a/o after if you want)
obj.value = before + '-' + selected + after;
// reset cursor position:
obj.selectionStart = pos;
obj.selectionEnd = pos;
}
Use the "ondblclick" attribute of your textarea to call the function:
<textarea ondblclick="dblClickEvt(this)"></textarea>
This only supports modern browsers, if you want to support older browsers, then you need to get the method that calculates selectionStart. This is not fully tested and if you double click on a line that is selected, it toggles the dash. And when you set the new value, the selection goes away.
$("textarea").on("dblclick", function (evt) {
var taValue = this.value;
//if there is no text than there is nothing to do
if(!taValue.length) return;
//get the position of the selection (not supported old browsers)
var se = this.selectionStart;
//find where the previous line break is located (array lastIndexOf not supported old browsers)
//thinking about it, probably do not need to split... :)
var loc = taValue.substr(0, se).split("").lastIndexOf("\n")+1;
//separate the text by characters
var parts = taValue.split("");
//if the character is a -, than remove it
if (parts[loc]==="-") {
parts.splice(loc, 1);
} else { //else inject the -
parts.splice(loc, 0, "-");
}
//join the array back up into a string and set the value
this.value = parts.join("");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows=10 cols=30>FOO FOO FOO
BAR BAR BAR
CAKE CAKE CAKE
WORLD WORLD WORLD</textarea>

Interactively, don't allow the first character in a text input to be a space, or group of spaces

Firstly, This is NOT a repeat question. Most of the similar questions, I've come across, don't preform the desired action interactively (e.g. "onkeydown", "onkeyup", etc.). I need a pure JavaScript (i.e. NO jQuery) function to disallow the first character of a text-based input to be a space or group of spaces given just the elements ID. Here is what I have:
<script type="text/javascript">
/* Don't allow the first character of a "text-based" input element
* (e.g. text-box, text-area, editable-div's) to be a space, given
* the elements ID ([ eID ]). [BEGIN]
*/
function noPrecedingSpace ( eID )
{
var elmt = document.getElementById(eID);
elmt.addEventListener("keydown", function(event)
{
var strg = elmt.value;
var lastChar = strg.charAt(strg.length - 1);
if ((lastChar == " ")||(lastChar == " ")||(strg == ""))
{
return event.which !== 32;
};
});
};
/* Don't allow the first character of a "text-based" input element
* (e.g. text-box, text-area, editable-div's) to be a space, given the
* elements ID ([ eID ]). [END]
*/
</script>
Any ideas as to why this is not working?
What am I doing wrong?
Please Note: "Paste" is already accounted for, and disallowed on the field by another javascript, that, by the way, is working perfectly.
JSFiddle
Returning true/false is the "old" way of managing event propagation. Better now is to use preventDefault()
var elmt = document.getElementById('noSpaces');
elmt.addEventListener('keydown', function (event) {
if (elmt.value.length === 0 && event.which === 32) {
event.preventDefault();
}
});
This just checks... if the current input length is zero then a space is not allowed.
Also see the fiddle.
You can add/modify to check for non-breaking spaces also, if that's really a problem -- match with a regex like Dave's answer, but only if elmt.value.length is > 0
This, however, would let you type non-spaces, then back-up to the start of the field and insert spaces.
A revised fiddle trims leading whitespace as you're typing, but this also won't entirely solve the problem.
var elmt = document.getElementById('noSpaces');
elmt.addEventListener('keydown', function (event) {
if (event.which === 32) {
elmt.value = elmt.value.replace(/^\s+/, '');
if (elmt.value.length === 0) {
event.preventDefault();
}
}
});
You can keep refining it, even taking the current caret position and the currently selected text into account, but ultimately you must .trim() the string you receive on the server, since I (for one) can send you anything I want to send despite all of your javascript efforts to make me enter a "legal" string.
You can test the value of the input with a regular expression to see if it starts with a space and if so remove the spaces from the start of the value;
var input = document.getElementById('noSpaces');
input.addEventListener('keyup', function(event) {
if(/^\s/.test(input.value)) {
input.value = input.value.replace(/^\s+/,'');
}
});
JSFiddle
Thanks to #StephenP, I have come up with this final answer, which is just perfect for my needs ("visitors_name" field):
<script type="text/javascript">
/* Don't allow the first character of a "text-based" input element (e.g. text-box, text-area, editable-div's, etc.) to be a space, given the elements ID ([ eID ]). Also, don't allow more than one space between adjacent words. [BEGIN] */
/* Usage Example: noPrecedingOrDoubleSpace ("visitors_name"); */
function noPrecedingOrDoubleSpace ( eID )
{
var elmt = document.getElementById(eID);
elmt.addEventListener("keydown", function(event)
{
var strg = elmt.value;
var lastChar = strg.charAt(strg.length - 1);
if ((lastChar == " ")||(lastChar == " ")||(strg == ""))
{
if (event.which === 32)
{
event.preventDefault();
};
};
});
};
/* Don't allow the first character of a "text-based" input element (e.g. text-box, text-area, editable-div's, etc.) to be a space, given the elements ID ([ eID ]). Also, don't allow more than one space between adjacent words. [END] */
</script>
Keep in mind that if you just need no space, only at the beginning of the input, #StephenP's answer is probably more practical, and is the real answer to this question, given the title.
Also remember, that just as #StephenP mentioned, real validation is best done in the server-side script (e.g. php). This JavaScript is just to encourage correct input formatting. Nothing more, nothing less.
Big kudos to #StephenP
Thanks!
Final JSFiddle.

How to remap keyboard within the same textarea

Currently i am doing a project with remapping characters to words by detecting the keyup function. Unfortunately, i have only been able to retrieve the first character and remap to the word i want. In my project, i need to directly retrieve all of my keyboard input and directly convert it to the word that i want within the same textarea. For example when i type in the textarea, it will convert to "are" directly. I don't know why it stopped retrieving the second character and remapping not function. Below is my code, hope someone can tell me my error. Thank you.
<textarea class="width-100" id="translated-text" onkeyup="myFunctionkey(event);" rows="10"></textarea>
<script>
function myFunctionkey(e) {
conversion();
}
function conversion(){
var x = document.getElementById('translated-text');
if(x.value == 'a'){
x.value='yes';
}
if(x.value == 'q'){
x.value = 'are';
}
}
</script>
From what I understand, you only want to grab the input and replace a key stroke with a complete word.
Maybe this will do. I've changed onkeyup to onkeypress because this is more reliable from what I remember.
<textarea id="translated-text" cols="50" rows="10" onkeypress="replaceInputChar(event);"></textarea>
<script type="text/javascript">
//create replacement map
var map = {
"a": "and",
"b": "bold",
"c": "change"
};
function replaceInputChar(e)
{
var ctl = document.getElementById("translated-text"); //control
var char = String.fromCharCode(e.keyCode); //typed char
if (char in map) //check if letter is defined in map
{
//insert replacement instead of letter
if("selectionStart" in ctl)
{
//in modern browsers we can easily mimic default behavior at cursor position
var pos = ctl.selectionStart;
ctl.value = ctl.value.substr(0, pos) + map[char] + ctl.value.substr(ctl.selectionEnd);
ctl.selectionStart = pos + map[char].length;
ctl.selectionEnd = ctl.selectionStart;
}
else
ctl.value += map[char];
if ("preventDefault" in e) //modern browser event cancelling
e.preventDefault();
else
{
//old browser event cancelling
e.returnValue = false; //IE8
return false;
}
}
}
</script>
You should use comparison operator '==' instead of assignment operator '=' while remapping the value, like this:
x.value=='a'
Edit:
You should check the updated code for your problem here:
https://jsfiddle.net/o4coLr5t/1/
Now, the characters you choose to remap in javascript will display the string, that you map the character to. Otherwise it will display nothing on pressing keys. So, try and add all the character keycodes to the javascript code. Hope that helps.

How to get first text node of a string while containing bold and italic tags?

String(s) is dynamic
It is originated from onclick event when user clicks anywhere in dom
if string(s)'s first part that is:
"login<b>user</b>account"
is enclosed in some element like this :
"<div>login<b>user</b>account</div>",
then I can get it with this:
alert($(s).find('*').andSelf().not('b,i').not(':empty').first().html());
// result is : login<b>user</b>account
But how can i get the same result in this condition when it is not enclosed in any element .i.e. when it is not enclosed in any element?
I tried this below code which works fine when first part do not include any <b></b> but it only gives "login" when it does include these tags.
var s = $.trim('login<b>user</b> account<tbody> <tr> <td class="translated">Lorem ipsum dummy text</td></tr><tr><td class="translated">This is a new paragraph</td></tr><tr><td class="translated"><b>Email</b></td></tr><tr><td><i>This is yet another text</i></td> </tr></tbody>');
if(s.substring(0, s.indexOf('<')) != ''){
alert(s.substring(0, s.indexOf('<')));
}
Note:
Suggest a generic solution that is not specific for this above string only. It should work for both the cases when there is bold tags and when there ain't any.
So it's just a b or a i, heh?
A recursive function is always the way to go. And this time, it's probably the best way to go.
var s = function getEm(elem) {
var ret = ''
// TextNode? Great!
if (elem.nodeType === 3) {
ret += elem.nodeValue;
}
else if (elem.nodeType === 1 &&
(elem.nodeName === 'B' || elem.nodeName === 'I')) {
// Element? And it's a B or an I? Get his kids!
ret += getEm(elem.firstChild);
}
// Ain't nobody got time fo' empty stuff.
if (elem.nextSibling) {
ret += getEm(elem.nextSibling);
}
return ret;
}(elem);
Jsfiddle demonstrating this: http://jsfiddle.net/Ralt/TZKsP/
PS: Parsing HTML with regex or custom tokenizer is bad and shouldn't be done.
You're trying to retrieve all of the text up to the first element that's not a <b> or <i>, but this text could be wrapped in an element itself. This is SUPER tricky. I feel like there's a better way to implement whatever it is you're trying to accomplish, but here's a solution that works.
function initialText(s){
var test = s.match(/(<.+?>)?.*?<(?!(b|\/|i))/);
var match = test[0];
var prefixed_element = test[1];
// if the string was prefixed with an element tag
// remove it (ie '<div> blah blah blah')
if(prefixed_element) match = match.slice(prefixed_element.length);
// remove the matching < and return the string
return match.slice(0,-1);
}
You're lucky I found this problem interesting and challenging because, again, this is ridiculous.
You're welcome ;-)
Try this:
if (s.substring(0, s.indexOf('<')) != '') {
alert(s.substring(0, s.indexOf('<tbody>')));
}

Categories

Resources