keep track of the position of a div in a textarea - javascript

I have a textarea that keeps track of a moveble div like this
$('#content').children().draggable({
drag : function () {
$('#textarea').text("left:" +($(this).position().left) + "px" + "\ntop:" + $(this).position().top + "px");
}
});
The problem is that if i write something in that textarea, it will stop updating the position if i move the div.
If the text in the textarea is like this:
blablablabla
left:10px
top:20px;
blablablablabla
I want to be able to write in the textarea and update the position if i move the div without the other content of the textarea being removed.
someone should be able write whatever they want in the textarea and if they move it, the position will appear a specific place or at the end of what they have written
Any ideas?
Example using ".val" instead of ".text": http://jsfiddle.net/Ydkrw/
".val" will remove the existing text...
Update: based on valentinos answer i did like so: http://jsfiddle.net/8G82U/
But this doesn't work if you write something in the textarea before you move it

This could be something to get you started. This is just a rough design that might help you. Used substring and replace javascript methods.
Fiddle

You could save the string denoting the position in variable, and replace only that string when you drag the div. Like this:
var position;
var oldposition = '';
$('#content').children().draggable({
drag: function () {
position = "left:" + ($(this).position().left) + "px" + "\ntop:" + $(this).position().top + "px";
$('#textarea').val($('#textarea').val().replace(oldposition, position));
oldposition = position;
}
});
http://jsfiddle.net/kCT9f/

Typically when I'm doing something like this I add a replacement keys to the content and replace it when I need to prepare the content.
<textarea>blablablabla {left: 10px} {top: 20px} blablablablabla</textarea>
Update the keywords when the div is moved like this.
$('#content').children().draggable({
drag: function(){
var text = $('#textarea').text();
// Replace Keys
text = replaceLengthKey(text, "left", $(this).position().left);
text = replaceLengthKey(text, "top", $(this).position().top);
// Return changes
$("#textarea").text(text);
}
});
function replaceLengthKey(source, name, value){
// Absolute length units: https://developer.mozilla.org/en-US/docs/CSS/length#Absolute_length_units
return source.replace(RegExp("\\{" + name + ":\\s*[0-9]*(px|mm|cm|in|pt|pc)?\\}", "gm"), "{" + name + ": " + value + "}")
}
Then, when you prepare the content as you want on the server or client, but at least the structure will be consistent.

You can enclose the position text within brackets and then when the div is moved apply a regular expression and change only the text within the brackets. Here is a working example.
var text=$('#textarea').val();
var newPos = "(left:" + ($(this).position().left) + "px" + "\ntop:" +($(this).position().top) + "px)"
text=text.replace(/ *\([^)]*\) */g, newPos);
$('#textarea').val(text);

Related

Change Color of counter while typing in

I am trying to do a Character Count while typing in, in a text area. i have got a working code to get the count.
the code is as follows
<script>
$(document).ready(function() {
$('#Description').keyup( function(){
var text_lengthDes = $('#Description').val().length;
var text_leftDes = (250 - text_lengthDes);
$('#Char_Count1').html(text_leftDes + ' Characters Left');
});
});
</script>
and it is called from a div where the count to be shown.
<div id ="Char_Count1"></div>
Now it works perfectly. I want this to change color when it exceeds the count so the user can see that he / she has typed in too many characters.
if anyone can help it would be great
Simply done:
<script>
$(document).ready(function() {
$('#Description').keyup( function(){
var text_lengthDes = $('#Description').val().length;
var text_leftDes = (250 - text_lengthDes);
var dHtml = (text_leftDes<0) ? '<span style = "color:red">' + text_leftDes + ' Characters left</span>' : text_leftDes + ' Characters left';
$('#Char_Count1').html(dHtml);
});
});
</script>
Set a css class for #Char_Count1 if the length exceeds the limit:
<script>
$(document).ready(function() {
$('#Description').keyup( function(){
var text_lengthDes = $('#Description').val().length;
var text_leftDes = (250 - text_lengthDes);
$('#Char_Count1').html(text_leftDes + ' Characters Left').toggleClass("limit", text_leftDes < 5);
});
});
</script>
then use css to give the element with the class the desired color
.limit { color: red; }
Like Paolo said, it would be possible to use a style directly, but it is good practice to use style only in style sheet files (css) instead of inline.
Don't create additional markup (html tags), this reduces readability and performance.
Just apply a style that makes the text colored (ex. red):
$('#Description').css( { "color", "#f00" } );
To let the color be toggled red/black appropriately depending on text length:
$('#Description').css( { "color", ( text_leftDes < 0 ? "#f00" : "000" ) } );
Side note:
As you're setting the text content of #Char_Count1 it's better to use jQuery's text() so you don't have to worry about escaping html:
$('#Char_Count1').text(text_leftDes + ' Characters Left');

JavaScript: why doesn't this simple animation test work?

<p id="test">Test</p>
<button onclick="move(getElementById(" test "))">click me</button>
function move(elem) {
var lft = 0;
function anim() {
lft++
elem.style.left = lft + "px";
if (lft == 100) {clearInterval(myVal);}
}
var myVal = setInterval(function(){anim()}, 500);
}
I'm just trying to get the "Test" text to move across the screen. This doesn't work.
http://jsfiddle.net/qfovLayv/2/
The left property only applies to positioned elements.
A positioned element is on where the value of the position property is something other than static.
static is the default value and you haven't changed it.
Set position to fixed, relative, or absolute depending on what you actually want.
Additionally, if you are using a " to mark the start an end of an attribute value, then the next " will end the attribute value.
onclick="move(getElementById("
If you want to use a " character as data in such a value, you must use a character reference: "
You could use ' instead.
Additionally, your ID doesn't have any spaces in it, so you shouldn't have any spaces in the string you pass to getElementById.

How to insert image node between text using javascript?

I need to insert image between the text where mouse click occurs such that the image inserts itself between the text and not overlap the text as can be seen in this jsfilddle.
$('#box').click(function(ev){
$('img.mover').clone()
.removeClass('mover')
.appendTo('body')
.css('left', ev.pageX-20)
.css('top', ev.pageY-20);
});
After the change basically it should look like mbmnB/img/Nmnbbmn if I click between B and N.
You can convert the text into nodes (span) and then detect the mouse click event on the nodes. Than split the text from that node and insert your image in between :
To convert in text node :
function wrapCharacters(element) {
$(element).contents().each(function() {
if(this.nodeType === 1) {
wrapCharacters(this);
}
else if(this.nodeType === 3) {
$(this).replaceWith($.map(this.nodeValue.split(''), function(c) {
return '<span>' + c + '</span>';
}).join(''));
}
});
}
wrapCharacters($('#box')[0]);
check this fiddle hope it helps:
Fiddle
Put every single letter into a span so that you can detect over which one the mouse is when the click event happens.
You should split your text in two inline parts. So best it would be to use span elements as they are inline and do not introduce newlines.
Later on you should get caret position. You can use this answer to get it: get caret position. Lets say you have your position inside var pos;
Then you can split:
function span(text) {
return '<span>'+text+'</span>';
}
var content = $('#box').html();
var left = span(content.substring(0, pos));
var right = span(content.substring(pos, content.length));
var img = '<img src="your_image.ext"></img>';
$('#box').html(left + img + right);
Note that this code is not tested but just displayes the mechanics.

showing context menu in contentEditable div

I have a contentEditable div with following text for example:
<div contentEditable='true'> This document is classified</div>
Now for example if user clicks on 'm' in word document I want to show a context menu containing few text choices. That context menu will be contained in a div element. I want to replace the word "document" with the option(text) selected by user from context menu. In my view I have to find absolute position of click to show context menu and then I have to find space elements before and after the caret position and then replace the selection with option selected from context menu. Any idea how I can do it using JavaScript and jQuery?
Edit:
one part of my question is about context menu and other the more important is how i can detect the word on wchich user has clicked on in contentEditable div or in text area on the other hand. my goal is something like in below picture
actually i want to make a similar transliteration application. the process of script conversion from roman to Urdu has been done however i m facing lot of problems in user interface development on the web. google transliteration application can be found here. i hope someone can help me in getting word under user's mouse and display a context menu containing few choices.
You may want to have a look at some of the existing context menu plugins
http://www.trendskitchens.co.nz/jquery/contextmenu/
http://labs.abeautifulsite.net/projects/js/jquery/contextMenu/demo/
http://plugins.jquery.com/plugin-tags/context-menu
To get the currently selected word in a text area, have a look at the fieldSelection plugin.
So using the second plugin and fieldSelection (Disclaimer: I think the indexing regarding string replacement is slightly off - have not fully tested)
Javascript
$(document).ready(function () {
//replace
$("#tx").contextMenu({
menu: 'replace'
}, function (action, el, pos) {
update(action, el)
});
function update(action, el) {
var range = $("#tx").getSelection();
var textLength = $("#tx").val().length;
var firstPart = $("#tx").val().substring(0, range.start);
var secondPart = $("#tx").val().substring(range.start, textLength);
var lastIndexofSpaceInfirstPart = firstPart.lastIndexOf(" ");
var firstIndexofSpaceInSecondPart = secondPart.indexOf(" ");
var startOfWord = 0
var endOfWord = 0
if (lastIndexofSpaceInfirstPart < 0) {
// start of string
startOfWord = 0;
} else {
startOfWord = lastIndexofSpaceInfirstPart;
}
if (firstIndexofSpaceInSecondPart < 0) {
// end of textArea
endOfWord = textLength
} else {
endOfWord = firstIndexofSpaceInSecondPart + range.start;
}
var word = $.trim($("#tx").val().substring(startOfWord, endOfWord));
var replaceMent = $("#tx").val().substr(0, startOfWord)
+ action.toString()
+ $("#tx").val().substr(endOfWord, textLength);
alert(
"rangeStart: " + range.start +
"\n\nrangeEnd: " + range.end +
"\n\nrangeLength: " + range.length +
+"\n\nfirstPart: " + firstPart
+ "\n\n secondPart: " + secondPart
+ "\n\n lastIndexofSpaceInfirstPart: " + lastIndexofSpaceInfirstPart
+ "\n\n firstIndexofSpaceInSecondPart:" + firstIndexofSpaceInSecondPart
+ "\n\nWordStart: " + startOfWord
+ "\n\nEndofWord: " + endOfWord
+ "\n\nWord: '" + word + "'"
+ "\n\nNew Text: '" + replaceMent + "'"
);
}
});
Html
<textarea id="tx">
Some text
</textarea>
<ul id="replace" class="contextMenu">
<li class="edit">youwordhere1</li>
<li class="cut separator">youwordhere2</li>
<li class="copy">youwordhere3</li>
<li class="paste">youwordhere4</li>
<li class="delete">youwordhere5</li>
<li class="quit separator">youwordhere6</li>
</ul>
To detect a word under the mouse cursor rock solid reliable: Just wrap every word you want to detect in a separate container, span for example. It is not difficult to do with javascript. Just parse the words in a loop and create span element for every one, then set its innerHTML = word. Then you can read the click event target and it will give you the span with the word.
To show a context menu on the spot is a trivial task:
Create a div with your content menu and make it positiion:absolute and display:none. When you want to show it, set its top and left styles (for example) equal to the target span element offset from the parent container and make its style display = "box". You are all set ;)

Numbering in jQuery

How could I change the text below so that the text within it has a number appended to it.
<div class="right">This is some text</div>
<div class="right">This is some text</div>
<div class="right">This is some text</div>
So the code above would become,
This is some text
This is some text
This is some text
you should use an ordered list... ol
or else you will need use css and add the content property your selector with the :after pseudo element.
How about the following?
$("div.right").each(function(i){
$(this).prepend((i + 1) + ". ");
});
UPDATE:
Here is one way that should work.
"number" is a custom element (it can be anything you want) that will/should be ignored by browsers.
$("div.right").each(function(i){
$(this).find("number").remove().end()
.prepend("<number>(i + 1) + ". </number>");
});
OR use the following which is probably a little slower but semantically correct...
$("div.right").each(function(i){
$(this).find("span.number").remove().end()
.prepend("<span class='number'>" + (i + 1) + ". </span>");
});
OR an even better way would be to prepend span.number before your first drag:
$(function(){ // document ready...
// caching the "numbers" will only work if you use the DOM
// for updating div position (like jQuery's "append()", "prepend()", "before()", and "after()") and not "innerHTML" or "html()"
var numbers = $("div.right").each(function(i){
$(this).prepend("<span class='number'>" + (++i) + "</span>. ");
}).find("span.number");
function dragEnd(){
// do your drag end stuff here...
numbers.each(function(i){
this.innerHTML = ++i;
});
)};
});
This is really an elaboration on another comment. I can't format code in a comment, I guess. You could use jQuery core's each:
$('div.right').each(function(ii){
html = $(this).html();
$(this).html(ii + '. ' + html);
});
jQuery selectors are your friend...
Get your stuff and loop on through something like this:
texts = $("div.right");
for(i = 0;i < texts.length;i++)
{
node = $(texts[i]);
content = node.html();
number = i + 1;
node.html(number + ". " + content);
}
Update: Jeez, last time post untested code straight off the dome here (disclaimer: not actually the last time). In the interest of correctness, I've updated it to at least run (and work!) if you still want to do it this way. Although I admit the other solutions are cleaner and more elegant.
Does this have to be done dynamically through jquery? Can't you just combine all that text into one div and then make a ordered list around it?
Using [] notation with a result set will give you the raw DOM element which does not have the html() function. Use the eq() function to get each element wrapped in a jQuery object.
You can also use each() as mentioned above, but I prefer straight 'for loops' so I don't have to adjust for 'this' if I'm in an event handler.
var texts = $("div.right");
var elem;
for(i = 1; i < texts.length; i++) {
elem = texts.eq(i);
html = elem.html();
elem.html(i + '. ' + html);
}

Categories

Resources