I found it really hard to come up with a question title for this one so I apologise that it's fairly cryptic but I'll try explain better there.
Basically part of an app I'm developing involves placing 'placeholders' in a textarea and then modifying those placeholders outside of the textarea.
For example:
This is the <first> placeholder. This is the <second> placeholder.
This is the <first> placeholder again.
Basically i have JS that detects these placeholders and creates input boxes to hold the text. So there would be an input text box for first and one for second.
What I want to achieve is when I type a value into the textbox it changes the placeholder in the textarea to the content being typed into the textbox. Think sublime text editor's snippets for a textarea.
I'm trying to figure out how I can track the placeholders in the text area. For example if a placeholder was <first_name> and i started typing into the placeholders textbox 'Billy'. I could easily change the placeholder by using a string replace function. However now the placeholder <first_name> doesn't exist in the textarea and so now I can't go back and change it. I need to have a way of tracking these placeholders whilst they are changing.
I hope that makes sense.
If you're not bound to a <textarea> element, you can try with a simple div with the attribute contenteditable="true". This way you can use some <span> to mark all the placeholders.
I set up a demo on jsfiddle, try it.
Using an element with contenteditable="true" would be easier for that task, because you could represent placeholders as span elements and you would then only have to retrieve them by id or any other unique attribute to update their content.
If you have to use a textarea and the users can only modify it's content using external inputs, maybe you could initially track the index of each placeholers and their length and keep those synchronized as values are changed.
You could then easily replace content in the textarea. For example, if the placeholder starts at 15 and has a length of 13.
var string = 'this is a test {placeholder} bla bla bla',
placeHolderIndex = 15,
placeHolderLength = 13;
string =
string.substring(0, placeHolderIndex)
+ 'new value'
+ string.substring(placeHolderIndex + placeHolderLength);
//update indexes of every placeholders that comes after this
//one and update the content length of this placeholder.
Obviously, you don't want to hardcode any values and you will want to handle this process in a dynamic way, but that's just an example.
NOTE: I guess users can modify the textarea content if you're using one. In that case, it would make things a bit more complicated, because you would have to update the index of the placeholders for every modifications the user does and you would also have to prevent them from editing the placeholders-mapped text directly.
Related
I am trying to change the value/text of a text node in canva.com.
I am able to change it visually but when I reload the page, or try to download the design, the old placeholder text is shown.
In canva when you change anything it automatically saves the changes, but you can also do this manually. I have tried manually saving but with no luck, only the old placeholder text is saved.
I have tried changing the text with the following methods.
The text is in a span so at first I tried to change that one.
var all_texts = document.getElementsByClassName("S1PPyQ");
all_texts[0].innerText = "HEY";
all_texts[0].textContent = "HEY";
all_texts[0].outerText = "hey"
After that I tried to get the parent node, which was a p tag. So basically the same code as above just with a different class name. This also did not work.
Any help is appreciated.
This is not one of those "how to insert text in input" questions. I've checked them all.
So I need to insert some text on page load into the message field on message.com.
The problem is that while the input is empty, it is just a <br data-text="true"> element. Then if you type something in, it changes to <span data-text="true"></span>. React does that.
I can add text to this span's innerHTML or textContent but in order for the tag to appear, I still need to type one letter manually into the message field. If i try to change innerHtml or textContent on br element nothing happens.
I tried selection and range:
let selection = window.getSelection();
let range = selection.getRangeAt(0);
let node = document.createTextNode(text)
range.insertNode(node);`
it kinda works, in a way that I just insert a new textnode, but I cannot send that text, so it is useless.
I spent all day on this and now I'm not even sure if it is possible.
OK, so for everyone who stumbles upon something similar, when you just can't change the DOM directly, as all the answers to similar problems suggest, here is my solution. It is SO simple.
You could use clipboard API. First you add the text to the clipboard with:
navigator.clipboard.writeText('text') It returns a promise in case you need it.
Then you paste the text at cursor position with document.execCommand('paste');
And that's it! In my case, as this was a part of my chrome extension, i also needed to put in the permissions key in manifest.json the following permissions: "clipboardRead", "clipboardWrite"
Good luck!
P.S. As i see tt is a new feature and is not available in IE and Safary.
I have created a Google Chrome extension to allow users to select text in a component. This works great for most sites. However, Facebook handles its status updates differently. It seems that even though you are filling in what seems to be a single text box, it is actually using a div > div > span > span construct for every single line in this text box. I have no idea why they chose to do this but it makes replacing multiple lines of text much more complex.
Is there a way to select multiple lines (or even contiguous portions of multiple lines) of text in a Facebook status update and replace the data?
The relevant portion of my code looks like this:
function replace_text(language){
let selection = window.getSelection();
string = selection.toString();
/* This section contains code that uses string.replace to replace characters in the string. */
document.execCommand("insertText", false, string);
}
Based on the way my code works now, if I replace text on a single line I have no problems. But, if I replace text that spans multiple lines I end up with a blank unusable input box. Undoubtedly it is because it is removing portions of the html code. How can I fix my code so that the replacement process works properly not only for other sites but also for Facebook?
As of this moment, the one common theme among all status updates (and comments) are that their texts reside within a single or set of span elements with the attribute data-text set to true. So let's target those:
document.querySelectorAll("span[data-text='true']");
For me, I've typed into the status field 3 lines and comment field 1 line of dummy text. So when I execute the above code into the console it returns an array of those four cumulative lines:
>>> (4) [span, span, span, span]
With that array, I can use the Array.prototype.forEach() method to iterate through the spans and replace the innerText:
document.querySelectorAll("span[data-text='true']").forEach(function(element) {
element.innerText = element.innerText.replace('Lorem ipsum','Hello world');
});
However, it is important to note that these changes are being made in the HTML itself and Facebook doesn't store all of its data directly in the HTML. Therefore it can cause undesirable events to occur when you type text into a field, unfocus, change the text in the field, and refocus that field. When you refocus I believe it grabs data of what the text was, before you unfocused that field, from an ulterior source like React's Virtual DOM. To deter it from doing that, the changes either need to be made after clicking the field (real or simulate) or as the user is typing using some sort of MutationObserver (src).
Suppose this is my textbox:
<input type="text" placeholder="%" />
And a user is supposed to enter a percentage inside, but without the % sign, only the numbers (e.g. 67 in 67%). But I want them to still remember that this is a text box in which you insert a percentage.
So how can I move the placeholder along with the text, make it unable to be deleted, always after the text?
And I do remember seeing it somewhere too, unless I got my facts wrong.
A way to do this would be to have an additional element overlaying the input element and moving the overlayed element as the user types.
But, I think a better UX experience would be to have the element as an add-on appended to the input field, as show in twitter bootstrap. See the "extending form controls" settings:
http://twitter.github.com/bootstrap/base-css.html#forms
You could simulate an input and change the width of the real input using javascript. (The trick is to use some invisible element to catch the needed width)
Exemple using JQuery: http://jsfiddle.net/Vu7hN/
$input.on('change keypress paste focus textInput input', function(){
testWidth.text($input.val());
$input.width(testWidth.width());
});
I'd like to be able to search the contents of a textarea (which will contain HTML markup that is visible to the user) with a specific regular expression that searches for specific attributes of all the HTML tags. Then I want to change the font color (within that same textarea) of the results of the search. Assume I have a submit button that will call a JS function that:
Creates a variable with the value of the textarea
Creates a variable with my regex search object
Searches the textarea.value with the regex string and changes the font color of all matches
Is this possible?
Yes. But it will take some work. More than likely, you'll need to swap out your textarea with a div and set its contenteditable attribute to true. Then you can wrap matched words with a span and set the font-color for those spans.
Rich text editing from MDN