divs, textareas, text and cursor detection - javascript

I have the following problems:
1.) I want to use a contenditable div or a textarea ( preferrably a contenteditable div because I can also use there html tags, not just text ), as a writing pad. However I want the writing to STOP once the cursor reaches the BOTTOM RIGHT corner of the div/textarea. This seems hard to implement. I have managed with max-height and overflow:hidden to make the element ( div / textarea ) to not expand, however the user can still type, it will just be invisible, something unwanted. What I want is the writing to stop when the cursor reaches the bottom right corner and then go on, on a new empty "page".
My first idea was to use some monospace font and calculate the max chars allowed but the issue is that 1st not all browsers show the same number of monospace characters of the same font, per line and 2nd the div can be variable in size, not constant.
The ideal would be a div so that i can enter html tags ( bold, italic, etc. ) and the div that shows the content can be of a different size, depending on the screen resolution.
2.) Given a div which represents a "page" which gets filled with a text/html from the database, how can I show only the content that fills the div, and when the user presses a "next page" button, show the next content. This seems undoable to me, figuring out via javascript how much content can fill into the div.
Any ideas on these two correlated problems would be greatly appreciated
No flash, no java, no plugins. only: html,css,javascript
Thanks in advance.

you can try the below code.
<div id="editable_div"></div>
var content_id = document.getElementById("editable_div");
max = 10;
//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(e){ check_charcount(content_id, max, e); });
$('#'+content_id).keydown(function(e){ check_charcount(content_id, max, e); });
function check_charcount(content_id, max, e)
{
if(e.which != 8 && $('#'+content_id).text().length > max)
{
// $('#'+content_id).text($('#'+content_id).text().substring(0, max));
e.preventDefault();
}
}

Related

Temporarily animate input type text when hovering

I want to show contents of an input type text if the text is wider than the current input width.
When I hover the field, I want the text to scroll to the left or something similar, in order to view the hidden text.
Thank you.
Note: tell me if I have to add/change the question's tags, please.
I thought about how I would do this and this is what I came up with.
On input hover I'm going to take the input value and put it in a div (or any other element). Then get the width of that div and compare it with the width of the input. If the div is wider than the input then I'm going to animate the inputs text-indent by the difference of the widths.
$('input').hover(function(){
var temp = $('div').html($(this).val()).width();
if($(this).width() < temp){
$(this).animate({
textIndent: $(this).width()-temp
}, 100);
}
});
You can see the full solution here: http://jsfiddle.net/taneleero/tB5C5/2/
Should be enough to get you going.
Eh, even though I did make that comment. couldn't resist this one myself. Using jQuery:
<input type="text" id="txt" value="A very long text goes here very long text goes here very long text goes here very long text goes here very long text goes here indeed."></input>
$('#txt').hover(
function() {
$(this).animate({"scrollLeft": this.scrollWidth}, this.value.length*50)
},
function() {
$(this).stop();
this.scrollLeft = 0;
}
)
here jQuery .animate() is used to animate .scrollLeft position of text within input field. Animation duration is tied to text length, so the speed should be the same for all kinds of texts. When mouse leaves input control - scroll position is reset to original.
Demo: http://jsfiddle.net/uPGmC/
If you googled a bit for "input text scroll left", you would find answers like this, combining it with jQuery docs on hover and animate you would piece the solution together yourself.

How to have transparent fonts except for the 'text-caret' in a textarea?

I have a simple textarea and I need to make transparent letters while allowing the text-caret to be visible. When I apply the following rules then I get invisible caret:
textarea {
background: transparent;
opacity: 0;
}
When I type invisible text, I need to see the text-caret move.
EDIT: I need to make editor to edit td cell in table. When I click on a cell I show a textarea and start typing. On a each character letter, I insert a context in a cell. After that, I hide a textarea.
This jsFiddle DEMO uses an online tutorial method that has been slightly modified to create a non-native browser text-caret along with transparent text.
Also, this jsFiddle New Method I created handles that goal differently but isn't IE8 friendly.
Status Update: I've improved the above jsFiddle DEMO with this newer version titled:
jsFiddle New Method that's Newer!!
The above jsFiddle version now allows the inside of the text-area to be clicked and the caret will respect that clicked location. This extra functionality was made possible by a great question and answer here.
Time to throw my $0.02 in.
This is an answer to the question, as I understood it, that works, it's quick and dirty, so feel free to make suggestions. This code is untested, but I did create a working fiddle here: http://jsfiddle.net/66RXc/
<html>
<head>
<title>Testing</title>
<script type="text/javascript">
<!--
function call(val) {
document.getElementById('result').value += val.charAt(val.length - 1);
document.getElementById('result').value =
document.getElementById('result').value.substr(0, val.length);
document.getElementById('test').value =
document.getElementById('test').value.replace(/[^\^]/g, ' ');
}​
-->
</script>
</head>
<body>
<textarea name="textarea" cols="20" rows="5" id="test"
onKeyUp="call(this.value);"></textarea>
<textarea style="display:block" cols="20" rows="5" id="result" disabled>
</textarea>​
</body>
</html>
The way I approached it was every time a character is typed in textarea "test", copy it over to a hidden text box, and replace all the characters in "test" except ^ with spaces. The characters are hidden, and the carat is still there. The full text is still in the other box. You could use display:hidden instead of display:block to hide it.
This isn't exactly the best implementation in the world, just something I did quickly. You have to type kind of slow (~15-20 WPM) for it to work.
Here is a CSS3 solution for making the text, itself, transparent:
Set the color attribute to be color: rgba(0,0,0,0); for the text
The only problem is that the caret goes invisible to. I did a quick search and found out that the caret and its styling are completely at the disposal of the browser. As such, the only option that I can think of for you is to use Javascript to add a simulated caret to the end of what you are typing.
I have an idea of how to do this, but it's messy and I wouldn't exactly call it ideal - I am, however, going to write it in case it helps further someone else's idea:
add a hidden label to the page
make sure it's hidden and not display: none; (so that it has actual width)
set white-space: nowrap; to keep it all on one line)
make sure the text is styled exactly the same as the text in the textarea
add the element <span id="caret">|</span> right before the textarea (I will refer to this as the caret for the rest of the spec)
set its position to position: relative;
increase its z-index to make it overlay
shift it right in order to set it on top of where the ACTUAL caret's initial position would be
make a function to check take in the value of the textarea and check the width of the textarea against the position of the caret (lookup selectionStart if you don't know how to do this)
the problem here is that characters are not always the same length, nor are they always the same length as their counterparts in other fonts
to solve this, as text is entered into the textarea you should have it imitated in the hidden label you created in step 1
imitate only the text from the start of the textarea to the caret's current position
wrap each character (including spaces) in their own span
next you will have to call a function to compare the width of the label with the width of the textarea
if the label is less wide than the textarea, get the width of the last span in the hidden label and shift the caret to the right by that width, then move on to step 4
as this is function will be run as text is entered it will happen one character at a time
be careful here that the caret doesn't go outside the textarea when it's in its last and near last positions
if the label is wider than the textarea:
add the widths of the characters (spans) in the label one at a time until you reach the width of the textarea
shift the position of the caret down by the height of the font and back to the horizontal starting position (as the caret's position is relative, just change its left position back to (0 + offsetToACTUALCaretPosition)
use a flag (e.g. class="break") to mark the last span (character) in the previous row
call the width comparison function again
make sure that you include a condition to check for the flags that you added at the end of each "row" (if any)
if you haven't already, apply any desired CSS styles to the caret span and change the color of the textarea's text to be color: rgba(0,0,0,0);
Caveats:
this will have a lot of overhead for the tiny job it does
you will have to adjust this method to account for padding
you will have to adjust this method to add support for deleting characters and moving the carets to an earlier position (to the left)
if you leave the textarea scrollable, you will have to add support for that (also for similar settings, like static heights causing text to scroll or move off screen/out of the textarea's visible area)
As I said before, I know that this solution is very rough, but it may help someone come up with a better one.
Good luck!
Based on your edit, if you need to just hide a textarea why don't you use jQuery $('#your_id').hide();

Scrolling textarea to specific area with javascript

I have a textarea with a scrollbar. I need to change the position of your cursor in the textarea with javascript AND scroll the textarea so your cursor is visible. I am using elem.selectionStart and elem.selectionEnd to move your cursor, but when I move it to a point that is not visible, the textarea does not scroll so the cursor is visible.
More details (probably TL;DR)
I am creating a slideshow editor and have a preview of the complete slideshow next to an editor (textarea with scrollbar) for the content. As you move your cursor through the textarea, the slideshow changes slides so you are always viewing the slide that you are editing. I need to get it so changing the slide (using buttons) moves your cursor so you can see the code that generated that slide.
// slideBoundries has numbers which are the indexes where the slides begin/end
// eg: [0, 81, 140, 250] for slideshow with 3 slides
if (doc.editor.selectionEnd > slideBoundries[curSlide] &&
doc.editor.selectionEnd < slideBoundries[curSlide + 1]) {
return;
}
doc.editor.selectionStart = slideBoundries[curSlide];
doc.editor.selectionEnd = slideBoundries[curSlide];
I could just count the number of newlines in the file so I know how far to scroll down, but there are many lines that are long and take up multiple lines. I am using a monospaced font so counting the number of newlines and lines that take up multiple lines, but I would like an easier way. Is there a function I could call to mimic what happens when the user moves their cursor as the textarea always scrolls to that point when the user clicks...
EDIT:
Due to popular demand, here is a fiddle: http://jsfiddle.net/tShQ2/
The method I'm going to use to fix this issue is create a phantom textarea that has same width, but autosizes to height. It has to be visible or else it won't work, so make it abs position and move it off screen. Then put the text before the desired cursor position in it. Then scroll the real textarea to the height of the phantom textarea.
Your solution is a good one, but let me suggest a couple of things to make it easier.
Use a phantom div, rather than a textarea, since a div will autosize automatically. Just make sure to match the styles.
To hide your phantom div use:
visibility: hidden;
position: absolute;
This has the same effect as display: none, while allowing the div to have a height.
One more thing. For IE, you can create a range from the selection and scroll to it explicitly:
document.selection.createRange().scrollIntoView();

How to find absolute or relative position of last letter inside an input field?

Maybe this is a strange question. Please, check Bellow you will understand.
Empty input type text, width=200px :
[____________________________]
Filled input type text, width=200px :
[abcdefg_____________________]
If input left is 0 how to find the absolute or relative position where the g letter is???
When user enters some text I want to display under last letter a simple div...
The text size hacks are OK, but you could alternatively use a visiblity: hidden span that moves your info div. HTML snippet follows:
<div><input type="text" value="hgello!!" onkeydown="document.getElementById('spacer').innerHTML = this.value;" /></div>
<div><span id="spacer" style="visibility: hidden;"></span>Character</div>
This way you can rely on the browser rendering the same font in roughly the same way into a span.
I can only think of one way to reliably do this, and it's quite dirty.
1) Use a content editable div floated left:
2) surround that div with another with a width of 200, border, and onlick sets focus to the editable div
3) put the div you want to show after the last letter after the editable div, also floated left
Result:
http://jsfiddle.net/tybro0103/zMezP/1/
Click on the box and start typing. The green box will move along with the cursor position.
In order to use this as a text field in a form you'll need to make a hidden input field. On form submit set the hidden field's value to editable div's inner html.
There is no built in "textWidth" param, sadly. However, a hack that will work pretty well: you can count the characters, guess at their width, and set your div "left" param equal to the character count * width (and make sure its absolutely positioned). something like:
var characterWidth = 6.8; //have to guess at this until it works...
var targetLocation = document.getElementById('yourInput').value.length * characterWidth;
document.getElementById('yourDiv').style.left = targetLocation + "px";
Run this script on a timer, every half second or so (or animate to the target location with jquery) and you should be in business.
Hope that helps.
As noted - this will only work if the font is monospaced and the user doesn't modify font size at all.
The only way I konw how to do that is to calculate the width of a letter then multiply it by the number of letter in your input.
Or
in a display:none div create a input width the maxlength attribute to the number of character in the current input. Then get the width of it.
set font size to input
make screenshot of input with text and see how much px used for 1 symbol (average)
count symblos * average width of 1 + input left padding = what you want :)
easy solution
I'm not really sure of the question but in my opinion you could do something like:
var len = 0;
$(document).ready(function(){
len = $('#input').val().length;
}
Now you could prepend the no of white spaces equal to the length in your target div.
Inspired by tybro's answer, I came up with this, which solves a problem in your question. If the textbox is a fixed length, what happens if the last letter is not visible at all? What co-ordinate should be reported then? Anyway, this gets around it by expanding the textbox indefinitely.
// markup
<div id="textbox">
<span id="edit" contentEditable></span>
<span id="end"></span>
</div>
<div id="report">x:? , y:?</div>
// css
#textbox {
border: solid black 1px;
min-height: 1em;
white-space: nowrap;
}
// javascript
$(function() {
$('#textbox').click(function() {
$('#edit').focus();
});
$('#edit').keypress(function() {
var endoff = $('#end').offset();
$('#report').html('x:' + endoff.left + ' , y:' + endoff.top);
});
});
The only thing I'm not sure of is when does keypress fire if it's before the content has changed, that's a problem. You could get round it by introducing a timeout or probably theres an even better solution. Unfortunately the keyup event doesn't seem to work on contentEditable things (in Firefox 5 anyway).
Hope this helps.

How to position an element below a text box carret in javascript?

I have a long text field and what I want to do is that when a user types an '#' character a list of users appear just like a typical auto-complete. However I want the list of users to appear below the '#' character which could be 20-30 characters in from the start of the text box.
I've found many jQuery auto-complete plugins but none that position the list below the current caret position.
I can get the text field position using $('#textfield').position() and I can get the caret position using something like this but that gets the character index from the text value and not the pixel position.
How can I get the current carret position of a text field relative to the page in pixels in order to position an element below it?
relaying on this anwsear: Calculate text width with JavaScript
what you can do is have a div on the screen which is visible:hidden
then every time a new charecter has been entered to the textbox change the inner html of the div
so the textbox value and the div innerhtml will always be synced.
then when you want to popup your autocomplete you will add the width of the div. to the
offset left postion of the textbox.
and thats it...
and avcorse you will need that the div and the textbox will have the same font...
This jQuery plugin does what you're after:
http://plugins.jquery.com/project/caretPosition
I haven't tested it, but going by the code it looks like it creates a temporary <span> with the same content as your <textarea> (up to the cursor) and makes wild assumptions about font, line height, whitespace and word wrapping when measuring it.
You could try extending it to:
Copy the font, line height, whitespace and word wrap styles from the target <textarea>
Hide the temporary <span> without affecting the measurement by wrapping it in a <div style="height: 0; overflow: hidden;"> or positioning it absolute -9999px, -9999px
$(this).position().top ;
$(this).position().left ;
$(this).position().right ; etc... :-)

Categories

Resources