How do you prevent formatted user input past a max width? (e.g., 800 pixels) The user input is formatted because it is entered into a WYSIWYG text editor (CK Editor).
This solution doesn't work:
// Replicate user input in hidden div
// Check width
// If width > 800px, remove characters
...because you'd be removing characters from a formatted entry - e.g., from <p>Hello World</p> you'd end up with <p>Hello World</p
I can already find the width of the
formatted string. The problem is in
the actually shortening of it.
I think given your problem it is possible to remove the last char from a formatted entry. You'd just have to recursively dig through your HTML structure till you find it. Have a look at this neat little function I've written:
function findLastElement(element){
var content = $.trim(element.html());
if(content.charAt(content.length - 1) === '>'){
var lastChild = element.children(':last');
if(lastChild.length > 0){
return findLastElement(lastChild);
}
}
return element;
}
The name is slightly misleading, but this function will dig through the jQuery element you pass to it to find the element containing the last character, so I think this will solve your problem.
PS. I'd readily accept any suggestion on how to optimize/adopt best practice with this piece of code, if any of the gurus here would kindly drop one in the comments.
Can we assume only a certain font will be used? This one might help:
Calculate text width with JavaScript
Related
There is a custom method to insert HTML(html fragment not just plain text) into an editor (Rich Text Editor), but for some reason I have to use e.preventDefault to prevent browser default paste action and insert the copy data later. My code looks like below:
editor.addEventListener('paste', function(e) {
var data = e.clipboardData.getData('text/html'),
newData;
e.preventDefault();
newData = custom.handle(data);
custom.insert(newData);
}, false);
After custom.insert(newData), cursor is still blinking at the origin position. I expected it to have moved the end of newData.
Can anybody help me fix that?
Your question may already have an answer here:
Use JavaScript to place cursor at end of text in text input element
Set focus and cursor to end of text input field / string w. Jquery
With Mike Berrow's example, you can replace the input value with itself to set the carret to the end of the input. This would seem to be the most reliable way to do it, event if it is slightly hackish.
myInput.value = myInput.value;
With browsers that support it, you can rather use the setSelectionRange method. Since you already use clipboardData, this shouldn't be a problem.
myInput.setSelectionRange(myInput.value.length, myInput.value.length);
Pay attention to the fact that the value length may be harder to get if you are working with a textarea.
https://developer.mozilla.org/fr/docs/Web/API/HTMLInputElement/setSelectionRange
I don't know what properties of functions your custom has, but you can use this the code to move the cursor to the end of the text in an input and textarea:
custom.selectionStart = custom.selectionEnd;
If newData is pasted in the middle or beginning of the text, then you will have to calculate the length of newData and move the cursor by that many characters. Something like:
custom.selectionStart = custom.selectionStart + newData.length;
custom.selectionEnd = custom.selectionStart;
Edit to answer your question: How to calculate the length of text with HTML tags?
Well, this will be a bit tricky. You can create a temporary HTML element in memory, add the newData in it, and calculate the length of its innerText property. Something like this:
var temp = document.createElement("div");
temp.innerHTML = newData;
custom.selectionStart = custom.selectionStart + temp.innerText.length;
custom.selectionEnd = custom.selectionStart;
Note: innerText is was introduced by Microsoft and is not a W3C standard. The implementation varies across browsers although most replicate IE's behavior. innerText is style-aware and will only return the visible text.
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.
I have a lot of text within a DIV. I would like to be able to search it on a string using perhaps a PHP regex then find the y position of that text that is searched on so I can place an image next to it.
I believe this would be the best way of doing it, I am unsure. However, I can't figure out how to determine how many pixels from the top of the screen that line is. Any recommendations?
#user1524441 not sure if this what you mean but from what I understand you want to add an image next to a specific search term, if this is the case you can use the following approach assuming you are using jquery:
var search = "Robin";
var text = $('.content').text();
$('.content').html(text.replace(search,'<span class="search-term" style="font-weight:bold;">' + search + '</span>'));
$('.search-term').before('<img src="url/goes/here" alt="" title=""/>');
here is a jsfiddle displaying how it works http://jsfiddle.net/6YsfB/
you can use substring and indexOf
var serch = "Robin"
var text = "hi my name is Robin, what you so talk? I'm god";
document.write(text.substring(text.indexOf(serch),text.indexOf(serch)+(serch).length));
http://jsfiddle.net/5bejQ/1/
If you're doing the search on the server, you could output the found text wrapped in <span> tags with a certain CSS class:
Here is some text with the <span class = "highlighted">text of interest</span> highlighted.
Then you could use the CSS "content" property (http://css-tricks.com/css-content/) in conjunction with the :before or :after pseudo-classes to show an image before or after the highlighted text.
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.
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