I have a <textarea> that has text added to it based on some javascript. It all works great. The only problem is, when the text is added, it replaces what was already there. Not sure how to stop this from happening, and make it just add to what is in there already.
js:
function addNote0(text, element_id) {
document.getElementById(element_id).value += text;
var tabTextRows = ['','','','','',''];
$('.note').click(function(){
var fret = $(this).index() - 1;
var line = $(this).parent().index() -1;
updateNote(fret, line);
});
function updateNote(fret, line){
var i;
for(i=0;i<tabTextRows.length;i++){
if(i == line) tabTextRows[i]+='-'+fret+'-';
else tabTextRows[i]+='---';
$('#tabText').val(tabTextRows.join('\n'));
}
}}
window.onload = function() {
addNote0('','tabText');
};
textarea that is being added to:
<textarea rows="6" cols="24" id="tabText" name="text">--
--
--
--
--
--</textarea>
So every time I click on a <td> it replaces the current "--" that is in there. I want it to just add to that. Any thoughts?
here is a jsFiddle of it. You will see what I mean when you click on the Xs
Instead of just putting in new content, grab the old content and concatenate it with your new content, then put that inside your textarea.
The easiest way to do this would be to just initialize your tabTextRows array in the beginning to:
var tabTextRows = ['--', '--', '--', '--', '--', '--'];
jsFiddle
Related
I am new to javascript. I was thinking getelementbyid but i don't know how to make it work
Like the title, here is what I mean
For example I have in HTML:
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
So what I want is to make script to replace those fw_93 fw_94 to what I want.
For example
Instead of displaying "fw_93" I want it to display "9.3". Same with fw_94 to 9.4
Replace fw_ with nothing, divide the number by 10:
Array.prototype.forEach.call(document.getElementsByTagName('p'), function(el) {
el.innerHTML = parseInt(el.innerHTML.replace(/[A-Za-z_]*/, '')) / 10;
});
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Okay so select the tags.
Loop over the collection
read the html
match the string
replace the html
var ps = document.querySelectorAll("p");
for (var i=0; i<ps.length; i++) {
var p = ps[i];
var txt = p.innerHTML; //.textContent
var updated = txt.replace(/.+(\d)(\d)/, "$1.$2");
p.innerHTML = updated;
}
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Using JQuery
Not sure why I did it with JQuery, guess I wasn't paying enough attention. No point in me re-writing as there are already good answers in JS. Though I will leave this in case it's of use to anyone that is using JQuery.
You can loop though each <p> element and covert the contents, something like this:
$("p").each(function() {
var text = $(this).html();
var text = text.substring(text.indexOf("_") + 1);
var text = text[0] + "." + text.substring(1);
$(this).html(text);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
You may need to add validation depending on how reliable your input is.
Note that the code makes the following assumptions:
There will always be a _ followed by at least 2 digits
The . will always go after the first digit
Your HTML:
<p id="p1">init_value</p>
Your JS:
document.getElementById("p1").innerHTML = "new_value";
I have <span> tags in a div that is removed when user clicks on them. Works fine.
I want to store the .text() inside that div in a variable. The problem is that the updated text doesn't get stored.
Click on a word to remove it in this jsFiddle.
As you can see, the content variable returns the old text, not the new revised one.
How can I store a variable with the updated text?
jQuery:
jQuery(document).ready(function() {
jQuery(document).on("mousedown", ".hello span", function() {
// don't add full stop at the end of sentence if it already ends with
var endChars = [".", "?", "!"];
jQuery(this).fadeOut(function(){
var parentObj = jQuery(this).parent();
jQuery(this).remove();
var text = parentObj.find("span").first().html();
parentObj.find("span").first().html(ta_capitalizeFirstLetter(text));
text = parentObj.find("span").last().html();
if ( endChars.indexOf(text.slice(-1)) == -1 )
{
parentObj.find("span").last().html(text+".");
}
});
var content = jQuery(this).parent().parent().find('.hello').text();
alert(content);
});
});
The code to get the new text should be moved inside the fadeOut callback. Once the animation is completed and element is removed, then the innerText of the parent element will be updated. At this time, the updated content should be read from the DOM.
Demo
// Cache the element
var $el = jQuery(this).parent().parent().find('.hello');
jQuery(this).fadeOut(function () {
jQuery(this).remove();
// Irrelevant code removed from here
...
var content = $el.text();
alert(content);
});
Here's another simple demo with minimal code that'll help to understand the code better.
Demo
I tried to debug your jsfiddle in chrome, and it looks like the priority of your code is like this:
declare on this event - jQuery(this).fadeOut(function(){
get the the current data of the div var content = jQuery(this).parent().parent().find('.hello').text();.
alert your data without changes.
calling the funcntion of fadeout
I think all you have to do is to call your alert and 2 from your anonymous function of fadeout
Just put your alert inside the callback:
jQuery(this).fadeOut(function(){
var parentObj = jQuery(this).parent();
jQuery(this).remove();
var text = parentObj.find("span").first().html();
parentObj.find("span").first().html(ta_capitalizeFirstLetter(text));
text = parentObj.find("span").last().html();
if ( endChars.indexOf(text.slice(-1)) == -1 ) {
parentObj.find("span").last().html(text+".");
var content = parentObj.parent().find('.hello').text();
alert(content);
}
});
I am using jQuery and CircleType.js to have text show in a circular pattern. My question is how can I make the text in the circle a hyperlink? The circletype.js automatically removes any a elements that are used, and since this method puts a span tag around each letter, I am not sure how you could use circletype.js with a link.
Is there another way to to wrap text in a circular shape with links without using circletype.js? I am still a newb at JavaScript, so if there is a way to create the links with JS, then any help getting on to the right path to write the script for this would be great. My code below (minus the css):
<body>
<div id="img-container">
<p id="link-circle">
LINK ♦ LINK ♦ LINK ♦ LINK ♦ LINK ♦
</p>
<a href="#">
<div id="switch">
<form action="">
<input type="radio" id="left-radio" name="Column Select" value="left"/>
<input type="radio" id="right-radio" name="Column Select" value="right"/>
</form>
<span id="dbl-chevron">»</span>
</div>
</a>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$('#link-circle').circleType();
});
</script>
</body>
Here is an example:
Maybe even a way to overlay a div layer over the text to create links would work. But I am not sure which way to go with this. Thanks in advance for any help!
After looking at the plugin's code and playing with it, I discovered that it was the required LetteringJS plugin that was removing any tags.
They call it on line 33: $(elem).lettering();
Then I came up with an idea.
What can we do?
We can save the HTML of our element before it gets split up by LetteringJS.
Then, let it do its work.
After that, we can put our tags back around each letter that was contained in one.
Partial solution
Why "partial"?
My solution will only work on:
non self-closing tags: no <img/>, <input/>, etc. but I don't think that's likely to happen.
non nested tags: no <b><a></a></b>, but you can fake that with classes - see demo below.
How does it work?
We need to change CircleType's source code so that it does what we want. I've commented my code, but if you don't understand something, or find a mistake or an improvement to make, don't hesitate to tell me!
// trim spaces at the beginning and at the end
elem.innerHTML = elem.innerHTML.replace(/^\s+|\s+$/g, '');
// grab the HTML string
var temp = elem.innerHTML;
// replace any space that is not part of a tag with a non-breakable space ( )
elem.innerHTML = elem.innerHTML.replace(/<[^<>]+>|\s/g, function(s) {
return s[0] == '<' ? s : ' ';
});
// wrap each character in a span
$(elem).lettering();
var inTag = false, // are we between tags? (<i>here</i>)
isTag = false, // are we inside a tag? (<here></here>)
tagNum = -1, // how many opening tags have we met so far? (minus 1)
pos = 0, // character position (excluding tags)
dom = document.createElement('div'); // temporary dom
dom.innerHTML = temp; // clone our element in the temporary dom
var tags = dom.children; // children of the element
// for each of them, empty their content
for(var i=0, l=tags.length; i<l; i++){
tags[i].innerHTML = '';
}
// for each character in our HTML string
for(var i=0, l= temp.length; i<l; i++){
var c = temp[i];
// if it's a '<'
if(c == '<'){
// and if it's an opening tag
if(!inTag){
// increment the number of tags met
tagNum++;
// we're in a tag!
inTag = true;
}
else{
// otherwise we're in a closing tag
inTag = false;
}
// we're on a tag (<here>)
isTag = true;
}
// if it's a '>'
else if(c == '>'){
// we're not <here> anymore
isTag = false;
}
// if we're not <here>
else if(!isTag){
// if we're <b>here</b>
if(inTag){
// replace the span's content with our tag
elem.children[pos].innerHTML = tags[tagNum].outerHTML;
// put the letter back in
elem.children[pos].children[0].innerHTML = c;
}
// move forward in the spans
pos++;
}
}
Resources
JS Fiddle Demo
Updated plugin source
There are two possible ways of doing this with jQuery.
One is to do a wrapInner() on the div after the circle has been created.
The other is to do an click() event which will run a javascript redirect.
I would personally side with the wrapInner() method.
Wrap
<script type="text/javascript">
$( document ).ready(function() {
var link = $('#link-circle').find('a').attr('href');
$('#link-circle').circleType().wrapInner('');
});
</script>
Redirect
<script type="text/javascript">
$( document ).ready(function() {
$('#link-circle').circleType();
$('#link-circle').click(function() {
window.location.href = "your link here";
});
});
</script>
have you tried wrapping each linkwith <a> tags like:
<p id="link-circle">
LINK ♦
LINK ♦
LINK ♦
LINK ♦
LINK ♦
</p>
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/
I am using a 'contenteditable' <div/> and enabling PASTE.
It is amazing the amount of markup code that gets pasted in from a clipboard copy from Microsoft Word. I am battling this, and have gotten about 1/2 way there using Prototypes' stripTags() function (which unfortunately does not seem to enable me to keep some tags).
However, even after that, I wind up with a mind-blowing amount of unneeded markup code.
So my question is, is there some function (using JavaScript), or approach I can use that will clean up the majority of this unneeded markup?
Here is the function I wound up writing that does the job fairly well (as far as I can tell anyway).
I am certainly open for improvement suggestions if anyone has any. Thanks.
function cleanWordPaste( in_word_text ) {
var tmp = document.createElement("DIV");
tmp.innerHTML = in_word_text;
var newString = tmp.textContent||tmp.innerText;
// this next piece converts line breaks into break tags
// and removes the seemingly endless crap code
newString = newString.replace(/\n\n/g, "<br />").replace(/.*<!--.*-->/g,"");
// this next piece removes any break tags (up to 10) at beginning
for ( i=0; i<10; i++ ) {
if ( newString.substr(0,6)=="<br />" ) {
newString = newString.replace("<br />", "");
}
}
return newString;
}
Hope this is helpful to some of you.
You can either use the full CKEditor which cleans on paste, or look at the source.
I am using this:
$(body_doc).find('body').bind('paste',function(e){
var rte = $(this);
_activeRTEData = $(rte).html();
beginLen = $.trim($(rte).html()).length;
setTimeout(function(){
var text = $(rte).html();
var newLen = $.trim(text).length;
//identify the first char that changed to determine caret location
caret = 0;
for(i=0;i < newLen; i++){
if(_activeRTEData[i] != text[i]){
caret = i-1;
break;
}
}
var origText = text.slice(0,caret);
var newText = text.slice(caret, newLen - beginLen + caret + 4);
var tailText = text.slice(newLen - beginLen + caret + 4, newLen);
var newText = newText.replace(/(.*(?:endif-->))|([ ]?<[^>]*>[ ]?)|( )|([^}]*})/g,'');
newText = newText.replace(/[·]/g,'');
$(rte).html(origText + newText + tailText);
$(rte).contents().last().focus();
},100);
});
body_doc is the editable iframe, if you are using an editable div you could drop out the .find('body') part. Basically it detects a paste event, checks the location cleans the new text and then places the cleaned text back where it was pasted. (Sounds confusing... but it's not really as bad as it sounds.
The setTimeout is needed because you can't grab the text until it is actually pasted into the element, paste events fire as soon as the paste begins.
How about having a "paste as plain text" button which displays a <textarea>, allowing the user to paste the text in there? that way, all tags will be stripped for you. That's what I do with my CMS; I gave up trying to clean up Word's mess.
You can do it with regex
Remove head tag
Remove script tags
Remove styles tag
let clipboardData = event.clipboardData || window.clipboardData;
let pastedText = clipboardData.getData('text/html');
pastedText = pastedText.replace(/\<head[^>]*\>([^]*)\<\/head/g, '');
pastedText = pastedText.replace(/\<script[^>]*\>([^]*)\<\/script/g, '');
pastedText = pastedText.replace(/\<style[^>]*\>([^]*)\<\/style/g, '');
// pastedText = pastedText.replace(/<(?!(\/\s*)?(b|i|u)[>,\s])([^>])*>/g, '');
here the sample : https://stackblitz.com/edit/angular-u9vprc
I did something like that long ago, where i totally cleaned up the stuff in a rich text editor and converted font tags to styles, brs to p's, etc, to keep it consistant between browsers and prevent certain ugly things from getting in via paste. I took my recursive function and ripped out most of it except for the core logic, this might be a good starting point ("result" is an object that accumulates the result, which probably takes a second pass to convert to a string), if that is what you need:
var cleanDom = function(result, n) {
var nn = n.nodeName;
if(nn=="#text") {
var text = n.nodeValue;
}
else {
if(nn=="A" && n.href)
...;
else if(nn=="IMG" & n.src) {
....
}
else if(nn=="DIV") {
if(n.className=="indent")
...
}
else if(nn=="FONT") {
}
else if(nn=="BR") {
}
if(!UNSUPPORTED_ELEMENTS[nn]) {
if(n.childNodes.length > 0)
for(var i=0; i<n.childNodes.length; i++)
cleanDom(result, n.childNodes[i]);
}
}
}
This works great to remove any comments from HTML text, including those from Word:
function CleanWordPastedHTML(sTextHTML) {
var sStartComment = "<!--", sEndComment = "-->";
while (true) {
var iStart = sTextHTML.indexOf(sStartComment);
if (iStart == -1) break;
var iEnd = sTextHTML.indexOf(sEndComment, iStart);
if (iEnd == -1) break;
sTextHTML = sTextHTML.substring(0, iStart) + sTextHTML.substring(iEnd + sEndComment.length);
}
return sTextHTML;
}
Had a similar issue with line-breaks being counted as characters and I had to remove them.
$(document).ready(function(){
$(".section-overview textarea").bind({
paste : function(){
setTimeout(function(){
//textarea
var text = $(".section-overview textarea").val();
// look for any "\n" occurences and replace them
var newString = text.replace(/\n/g, '');
// print new string
$(".section-overview textarea").val(newString);
},100);
}
});
});
Could you paste to a hidden textarea, copy from same textarea, and paste to your target?
Hate to say it, but I eventually gave up making TinyMCE handle Word crap the way I want. Now I just have an email sent to me every time a user's input contains certain HTML (look for <span lang="en-US"> for example) and I correct it manually.