TinyMCE how to dynamically get line breaks in a textarea - javascript

I need advice on how I can create dynamic line breaks ideally with an <li> inside TINY. I have tried using an each loop and also a for loop, and the values just do not appear in the text area. BUT, if I just add them to the text area with a val() they go in fine, BUT as just one long string.
The text area has an id of wo_materials. I'm successfully getting my text into Tiny like this:
$('#wo_materials').val(materials);
tinymce.init({
selector:'textarea'
});
And I get a nice row of text values:
The materials value is an array. If I look at it in the console it looks like this:
0: BP #15 Plain Felt 36"
1: Duraflo Weatherpro 50
2: 1 1/4 Coil Nails - box
Thanks !

If you're only modifying the value of the text area before tinymce is initialized then this might work for you:
$('#wo_materials).val(materials.join('<br/>'));

This works. The secret is adding the incrementing var "text" to the for loop and then wrapping the object / array in an <li>
var materials= JSON.parse(localStorage.getItem('materials'));
var text=" ";
materials.length;
function workorders(){
for (i = 0; i < materials.length; i++) {
text += "<li>"+materials[i]+"</li>";
}
$('#wo_materials').val("<li>"+text+"</li>");
}
workorders();

Related

Avoiding extra use of span

My question is that I have an html code <p> Hello World </p>
And want to change the css of every letter using JavaScript. Essentially, I will change the background color to make an animation. Is there a way to do this without making a span or some sort of tag around every letter and going through all that struggle?
I have my string array with colors and a method to call the correct color (data-index attribute).
Thanks!
EDIT: I have the entire word changing color and thought of an idea by making a function that iterates over the indexes of the innerHTML string and assigns a data-index to the letter's span by editing the function provided below by Cymen. Is this a good approach?
No, you will need to use a tag that supports background-color. You can easily wrap a string of characters in spans like so:
function wrapInSpans(string) {
return '<span>' + string.split('').join('</span><span>') + '</span>';
}
You would have to use a JavaScript function to wrap each character in a <span>.
window.onload = function() { // when everything loads, run the function
var elem = document.getElementById( "someId" );
var text = elem.innerHTML; // get the <p>'s text content
elem.innerHTML = ""; // then make the <p> empty
for( var i=0; i<text.length; i++ ) { // for each character in the text
elem.innerHTML += "<span>"+text[i]+"</span>";
}
};
Remember to change "someId" to the id of your <p> element.
You can access each individual character inside the for loop with text[i].
This would take quite a bit of code to spell out completely, but, if it's very important in your case to not actually add some type of wrapping element, then I believe this would be possible via a dynamically generated background image.
Roughly the steps would be:
Create a Range with a start and end around each character in the .textContents of the element you care about.
.getBoundingClientRect() on each range to get its rendered dimensions.
Draw rectangles of the desired color to a <canvas>.
Export the <canvas> as a data URI.
Use the data URI as a background-image.
Repeat for each block displayed element that you care about.
Be advised that there will, no doubt, be various edge cases in this approach and possible browser support limitations. Obviously just wrapping each character is a much simpler.

How to use innertHTML, in this following situation

We were given an assignment to basically make a Madlib by having the user enter words into textfields and then replacing words in a hidden paragraph existing in the html page. We have to use JavaScript and CSS.
the paragraph in the html page:
<span id="story" display="hidden">
Rain was still lashing the windows, which were now <span id="adjs1">__adjective__</span>, but inside all looked bright and cheerful. The firelight glowed over
the countless <span id="adjs2">___adjective___</span> <span id="plnouns">___plural_noun___</span> where people sat <span id="verbs1">___verb_with_ing___</span>
, talking, doing homework or, in the case of Fred and George Weasley, trying to find out what would happen if you fed a <span id="foods">___food___</span> to a
<span id="monsters1">___monster___</span>. Fred had "rescued" the <span id="adjs3">___adjective___</span>, fire-dwelling <span id="monsters2">___monster___</
span> from a Care of Magical Creatures class and it was now<span id="verbs2">___verb_with_ing___</span> gently on a table surrounded by a knot of curious peopl.
</span>
Everything was going fine till I keep missing on getting the results I want.
function generateMadlib(){
// Display the story. The story is initially hidden.
document.getElementById("story").style.display = "inline";
// Get the words from the textboxes.
var formElements = $("#madlibForm :text");
// Find the word locations on the hidden paragraph.
var storyWords = $("#story span");
// Replace word loc values with with formElement values
for (var i = 0; i < formElements.length; i++)
{
storyWords.eq(i).innerHTML = formElements.eq(i).val();
}
}
This line
storyWords.eq(i).innerHTML = formElements.eq(i).val();
doesn't change the values inside the spans within the paragraph. (the code returns the proper input on the textfields)
I also tried using the browser console and manually changing document.getElementById("adjs1").innerHTML = "test"; it will return "test" but the value doesn't actually change. Can anyone clarify what .innerHTML actually does?
.eq(i) returns a jQuery object so it don't have the innerHTML property, so you can use .html() to set the html content
storyWords.eq(i).html(formElements.eq(i).val())
or you can use .get() which will return a dom element reference
storyWords.get(i).innerHTML = formElements.eq(i).val();
But you can simplify the overall implementation like
function generateMadlib() {
// Display the story. The story is initially hidden.
$("#story").css('display', "inline");
// Get the words from the textboxes.
var formElements = $("#madlibForm :text");
$("#story span").html(function (idx) {
return formElements.eq(idx).val();
})
}

jquery & doc.createElement throws error for <

Both the $("<test") & document.createElement(",test") throws error due to < character associated to the text. I do not want to replace the character & wanted to see if there is option to create dom or jquery object using such text. I know replace will work but since the code is pre-existing & also since code is written such that it assume it can either have the simple text (textnode) or html tag (like span) hence this error is occuring as it fails to check if it is proper self closing html tag.
I am thinking of creating it to xml node & then check if the childnode is textNode or not before trying to create jquery object,however I am looking for suggestion & best approach to tackle such issue. I know replace of < will work & also there is no need to check for attributes of plain text but since the code is dynamic it sometimes retrieves plain text & some time it gives valid html tag that why this issue appears
I am not sure what your exact end goal is, but basically you need to do something like this:
function makeElemHack( str ) {
var div = $("<div>").html(str); //create a div and add the html
var html = div.html(); //read the html
if (!html.length) { //if the html has no length the str was invalid
div.html(str.replace(/</g,"<")); //escape the < like text should be
//div.text(str); //or you can just add it as plain text
}
return div; //with the div wraper
//return div.contents(); //without the div wrapper
}
var bd = $("body");
bd.append( makeElemHack("<p>Hello</p>") );
bd.append( makeElemHack("1<0") );
bd.append( makeElemHack("<booo") );

How do I select arbitrary text on the page using javascript?

Let's say I have a contentEditable div, to the user can edit and change the text and elements inside it. How do I arbitrarily change the selection in this div with javascript? By "change" I don't mean "change the contents of whatever the user has selected", I mean actually change what is selected. The user should then be able to type over the selection, replacing it with something else.
This should take into account that I may want to select text across elements. For instance:
<p>Some text <span>goes</span> here.</p>
I may for instance want to select "Some text go", or everything inside the <p>.
This only needs to work in Safari/Webkit.
Thanks in advance. As a native code developer, I find the DOM and Javascript in general quite frustrating.
Just to answer my own question in detail so anyone searching for something similar doesn't have to go looking elsewhere...
The code I ended up using was something like this:
var range = document.createRange();
range.setStart( <get the node the selection starts in>, <char offset in that node> );
range.setEnd( <get the node the selection ends in>, <char offset in that node> );
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
Big thanks to James Black for pointing me in the right direction.
Unless you need to write your own, you may want to look at tinyMCE, http://tinymce.moxiecode.com/, as it is a nice WYSIWYG editor in javascript.
In order to do this you will probably want to look at something like this:
http://codingtricks.blogspot.com/2009/03/javascript-select-partial-text-in-div.html
These may also be helpful:
JavaScript ranging gone wrong
https://developer.mozilla.org/en/DOM/window.getSelection
What you are trying to do will be complex, as you will need to take the selected area, remove all the tags, then put in the tag that you want for the selected area.
You can use document.getElementById('your_text_id').setSelectionRange(start, end); and you can use Math.random() to generate random numbers for start and end
While #Lucas's answer is good, there is a lot missing that would allow you to successfully use this. The node the selection starts in has to be the exact node, not a parent. In our case we were trying to put some text into a TextAngular control, then select text that looked liked ____ so the user could "fill in the blank".
Our input was html of the order <p>Some text goes here: _____</p> or
<p>Some partial goes here
<ul>
<li>Option 1</li>
<li>_____</li>
</ul>
To get this to work, we had to write something to find the underscores in the right element
function find_(node) {
var i, n;
// return the node with the _'s
for(i=0; i < node.childNodes.length; ++i) {
n = node.childNodes[i];
console.debug(n);
if(n.textContent) {
console.debug(n, n.textContent);
if(n.textContent.search(/___+/) > 0) {
return n;
}
}
if(n.childNodes) {
console.debug(n, n.childNodes);
n = find_(n);
if(n) {
return n;
}
}
}
return null;
}
So in the end, finding the node to satisfy <get the node the selection starts in> was a lot more work than that simple sentence led me to believe.
In the <ul> case. the node that contains the ____ is firstChild of the li node.
I've put this here to help others that need to do this not wonder why they are getting the error message
IndexSizeError: Failed to execute 'setStart' on 'Range': There is no child at offset 65.
When the problem is they are just looking at the wrong node.

Display current line and column number for a textarea

I'm making a file edit interface in my web-app, I have a textarea with file contents.
When textarea is focused, I want to output the position of the cursor, i.e. line number and column: this is useful because error messages usually yield a line number, for example.
The question is: how do I figure out the position of the cursor in textarea?
I'm using prototype library. Maybe there's a solution already?
I'm not really interested in fancy toolbars for the textarea, which are offered by those advanced widgets.
When I want the current line number of textarea and current column of textarea, I solved like this:
<textarea onkeyup="getLineNumberAndColumnIndex(this);" onmouseup="this.onkeyup();" >
</textarea>
function getLineNumberAndColumnIndex(textarea){
var textLines = textarea.value.substr(0, textarea.selectionStart).split("\n");
var currentLineNumber = textLines.length;
var currentColumnIndex = textLines[textLines.length-1].length;
console.log("Current Line Number "+ currentLineNumber+" Current Column Index "+currentColumnIndex );
}
You may want to check out these 2 links:
http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/[The orginal source does not exist any more, the modified link points to the latest version of the Web Archive]
https://developer.mozilla.org/En/DOM:Selection
..once you have a selection (cursor index in text), you can split your text by newlines, thus getting line number. you can get column by determining index from beginning of a line

Categories