I'm creating a an html/javascript application as a project where I essentially am creating a markup language and converting the text to pictures. One thing I am doing for this is making it possible to copy and paste the string of pictures into the text area and get the markup version so that I can save it in text format.
I accomplish this by setting the alt attribute of my html images to what I want to be copied. Something I'm having trouble with is that when I set it up so that it prints the images "down" instead of to the right, accomplished by creating a sequence of <div><img alt="words" src="picture"></img></div> it interprets it as having newline characters between each individual pictures alt when I copy and paste.
I've tried adding a backspace character but that obviously failed, does anybody have a solution for getting rid of these newline characters?
Here's a picture of the output and what you get when you copy and paste to help make it more clear
var pasteArea = document.getElementById('pasteArea');
pasteArea.addEventListener('input', function () {
var value = pasteArea.value;
var spaceRemoved = value.replace(/\n/g, '');
if (value !== spaceRemoved) {
pasteArea.value = spaceRemoved;
}
});
You can attach an event to your textarea that removes any whitespace (or just newlines if that's preferable) when the value changes:
var pasteArea = document.getElementById('pasteArea');
pasteArea.addEventListener('input', function () {
var value = pasteArea.value;
var spaceRemoved = value.replace(/\s/g, '');
if (value !== spaceRemoved) {
pasteArea.value = spaceRemoved;
}
});
textarea {
height: 10em;
width: 300px;
}
<textarea id="pasteArea"></textarea>
Related
I'm building an autosuggest/autocomplete feature in a contenteditable div and I'm having a problem with determining when the cursor comes after characters that don't qualify for autocompletion. What I want to do is run my autosuggest ajax request only if the user is typing an "#" handle, such as "#someUser". The problem is that contenteditable divs contain actual html, so I'm tripping up when trying to determine if the last character before the cursor is one of my approved characters. My approved characters are: A-z0-9. I'm using this regex: /( $| $|\s$)/, but it only checks for spaces. I can't simply negate my approved characters (something like [^A-z0-9]) because the HTML of the contenteditable would cause false negatives (the contenteditable div can have something like <div>test</div> as its innerHTML). I created this demo to try to showcase the problem.
Here is the code for it:
document.querySelector('button').addEventListener('click', handleClick);
function handleClick(e) {
const inputField = document.querySelector('#edit-me');
const text = inputField.innerHTML;
if (!text) {
alert('no text');
}
const afterInvalidChar = isAfterInvalidChar(text, getCaretIndex(inputField));
if (afterInvalidChar) {
alert('cursor is not after an accepted char');
} else {
alert('cursor is after an accepted char');
}
}
function isAfterInvalidChar(text, caretPosition) {
// first get text from the beginning until the caret
let termToSearch = text.slice(0, caretPosition);
console.log(termToSearch);
alert('content before cursor: ' + termToSearch);
const rgxToCheckEnding = /( $| $|\s$)/; // <-- this is where I'm tripping up, that regex only checks for spaces, and it's still not great
if (rgxToCheckEnding.test(termToSearch)) {
// the cursor is after a space, but I also need to check for anything
// that's not one of my accepted contents
return true;
} else {
return false;
}
}
// source: https://stackoverflow.com/a/46902361/7987987
function getCaretIndex (node) {
var range = window.getSelection().getRangeAt(0),
preCaretRange = range.cloneRange(),
caretIndex,
tmp = document.createElement("div");
preCaretRange.selectNodeContents(node);
preCaretRange.setEnd(range.endContainer, range.endOffset);
tmp.appendChild(preCaretRange.cloneContents());
caretIndex = tmp.innerHTML.length;
return caretIndex;
}
#edit-me {
width: 200px;
height: 200px;
background-color: lightblue;
}
<h2>Cursor of contenteditable div</h2>
<p>Accepted chars: <code>A-z0-9</code></p>
<button type="button">is cursor after an accepted char?</button>
<div contenteditable id="edit-me"><div>
An accceptable solution should work with the following text in the contenteditable div (just basic tests but you get the point):
"test": correctly say the last char is approved
"test ": correctly say the last char is not approved
"test-": correctly say the last char is not approved
"test?": correctly say the last char is not approved
How can get this working for only my approved chars? I'm open to an entirely different strategy if it gets the job done. Thanks!
The problem is that you need to decode HTML entities.
You can easily do it with this function
function decodeHTML(htmlString) {
var txt = document.createElement('div');
txt.innerHTML = htmlString;
return txt.textContent;
};
basically what it does is it makes an imaginary div and places the html code in the content of the div, and you get plain text when you request the contents using textContent.
Now all you have to do is change termToSearch to decodeHTML(text.slice(0, caretPosition)); and make your regex to check the ending
Please note that the function will not acctually make a div tag, but will still return the decoded values. The reason for this is because document.createElement() just makes an object of an HTML element rather than an actual element.
Is it possible to change font weight if last character is colon with JavaScript?
I have site, where people can add recipe. And i want to highlight parts of ingredients of recipe. For example:
topping:
-chocolate
-milk
filling:
-...
-...
I searched and i found that codes:
for last character
if (myString.charAt(myString.length - 1) == ':')
and for weight change
function changeWeight(600)
{
document.getElementById("id_1").style.fontWeight = fontWeight;
}
I do not know how to write the code to work. I am beginner.
Thank you very much.
Try this
if (myString.charAt(myString.length - 1) == ':') {
changeWeight("600");
}
function changeWeight(weight) {
document.getElementById("id_1").style.fontWeight = weight;
}
It seems that you want to make specific text bold, not all text within an element. You would need to get the text out of the element, change it, and put it back.
You can use code like this to but a bold tag around all words in the element that ends with a colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
text = text.replace(/([A-Za-z]+:)/g, '<strong>$1</strong>');
element.innerHTML = text;
Note: For that to work properly, you can't have other HTML elements inside the element that has words with colons in the actual markup. I you have for example SO in the code, it would break because of the http: in the link.
If you have that single word alone in an element, you would get the text and check for the colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
if (text.charAt(text.length - 1)) == ':') {
element.style.fontWeight = 'bold';
}
i'm makeing a tinyMce plugin that change word/letter space between highlighted text. My fn() looks like this:
function wordsLettersSpace(words, letters) {
var inst = tinyMCE.activeEditor;
var currSelection = $.trim(inst.selection.getSel());
if(currSelection != ""){
var content = "";
content = inst.selection.getContent({
format: 'html'
});
contentReplace = '<span style="word-spacing: '+words+'px; letter-spacing: '+letters+'px;">' + inst.selection.getContent({
format: 'html'
}) + '</span>';
inst.selection.setContent(content.replace(content, contentReplace));
window.alert(content);
}else{
Hyphenator.hyphenate(inst.getBody(), language);
}
tinyMceUpdate();
}
Now i need to find closest tag before select start position (if exist) and get style values of "word-spacing" and "letter-spacing". Also i need to get rid of any inside of selection, but only tags not the text, knowing that span tags can have different styles so simple str.replace won't work.
I know that there is a built-in plugin for that, but i need to do it outside of tinyMce iframe, and customize it.
Any sugestions?
JS regexes are available and do exactly what you want with preg_match.
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions
Substring in javascript is str.substr(start, length)
I have a div tag with contenteditable set to true.
I am trying to find out the last entered word in the div.
For example, if I type in This is a test and I hit a space, I want to be able to get the word test
I want to be able to use this logic so that I can test each word being typed (after the space is pressed).
It would be great if someone could help me with this.
An easy solution would be the following
var str = "This is a test "; // Content of the div
var lastWord = str.substr(str.trim().lastIndexOf(" ")+1);
trim might need a shim for older browsers. (.replace(/\s$/,""))
To strip punctuation like " Test!!! " you could additionally do a replace like following:
lastWord.replace(/[\W]/g,"");
You might want to do a more specific definition of the characters to omit than \W, depending on your needs.
If you want to trigger your eventhandler also on punctuation characters and not only on space, the last replace is not needed.
You first have to know when the content is edited. Using jQuery, that can be done with
$("div").on("keyup", function(){ /* code */ });
Then, you'll have to get the whole text and split it into words
var words = $(this).text().trim().split(' ');
And getting the last word is as complicated as getting the last element of the words array.
Here's the whole code
HTML
<div contenteditable="true">Add text here</div>
JavaScript (using jQuery)
$("div").on("keyup", function(){
var words = $(this).text().trim().split(' '),
lastWord = words[words.length - 1];
console.log(lastWord);
});
Demo
This is the ultimate way:
// listen to changes (do it any way you want...)
document.querySelectorAll('div')[0].addEventListener('input', function(e) {
console.log( getLastWord(this.textContent) );
}, false);
function getLastWord(str){
// strip punctuations
str = str.replace(/[\.,-\/#!$%\^&\*;:{}=\_`~()]/g,' ');
// get the last word
return str.trim().split(' ').reverse()[0];
}
DEMO PAGE
You can try this to get last word from a editable div.
HTML
<div id='edit' contenteditable='true' onkeypress="getLastWord(event,this)">
</div>
JS
function getLastWord(event,element){
var keyPressed = event.which;
if(keyPressed == 32){ //Hits Space
var val = element.innerText.trim();
val = val.replace(/(\r\n|\n|\r)/gm," ");
var idx = val.lastIndexOf(' ');
var lastWord = val.substring(idx+1);
console.log("Last Word " + lastWord);
}
}
Try this link http://jsfiddle.net/vV2mN/18/
www.powersource.se
The last link, "Add some stuff" doesn't work properly. It's supposed to add a bit of text when you press it and then remove the text when you press it again. I've made the add-part work, but I haven't managed to make the remove-part.
function add_module(title, text)
{
container = document.getElementById('text-main');
the_text ='<div class="text-header" id="added-text-header">' + title + '</div><div id="added-text">' + text + '</div>';
if(container.innerHTML != container.innerHTML + the_text)
{
container.innerHTML = container.innerHTML + the_text;
}else if(container.div.innerHTML == container.innerHTML + the_text)
{
text_container = container.getElementById('added-text-header');
parent = text_container.parentNode;
parent.removeChild(text_container);
text_container = container.getElementById('added-text');
parent = text_container.parentNode;
parent.removeChild(text_container);
}
}
You're using + to add text in. That's how JavaScript concatenates two strings.
The problem comes when you try to use - to remove. That won't work. The minus sign is for subtracting numbers, not for taking something away from a string.
I'd suggest using jQuery or another JavaScript library that has good cross-browser DOM manipulation. When you insert more text in, use a function to add a chunk of HTML. Use the p tag: <p>some text</p>. Then you'll be able to hunt down the p tags and delete the last one.
When you say string1 + string2 you're actually creating a brand new string, + is just shorthand for "mash these two together."
If you want to be able to add and remove that text you'll have to do it another way. The real issue is that once you've concatenated the strings together you have no idea which part of the string is the original, and which part is the user's.
In jQuery you can use DOM manipulation to better handle this. First I would put your div tags with the text-header and the text inside your container, but leave them empty. That way you don't have to create them on the fly. Then (assuming your text div has a class of "text-body"):
var textHeader = $("#text-main .text-header");
var textBody = $("#text-main .text-body");
//If the header doesn't contain the title set it, otherwise remove it
if(textHeader.text() != title) {
textHeader.text(title)
} else {
textHeader.text("");
}
//If the text body doesn't contain the text set it, otherwise remove it
if(textBody.text() != text) {
textBody.text(text)
} else {
textBody.text("");
}