This is my little jquery plugin that replaces each english symbol with other symbols while typing. Everything works fine here except when I type a long word, longer than the input itself, the cursor goes outside the input the the last part of the word isn't visible. Just visit the link bellow and type something (without the space) and you'll get what I mean.
http://jsfiddle.net/beLMf/
Is there any solution to fix this?
You have two problems one is that you add the text to then end of the line all the time that is if it matches the characters you are looking for. You should instead do the insert at the caret(cursor) position:
jQuery.fn.extend({
insertAtCaret: function(myValue){
return this.each(function(i) {
if (document.selection) {
//For browsers like Internet Explorer
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
}
else if (this.selectionStart || this.selectionStart == '0') {
//For browsers like Firefox and Webkit based
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)+myValue+this.value.substring(endPos,this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
})
}
});
Then change your line:
$this.val( $this.val() + String.fromCharCode( i + 4304 ) );
to
$this.insertAtCaret(String.fromCharCode( i + 4304 ));
$("#switcher").focus();
$(this).focus();
that will solve your issue and also solve the problem of editing any part of the string.
update:
To make the cursor position update we have to switch focus away and then back to the element
I made the changes to jsFiddle there is also a function to capture cursor position that I was thinking of using to solve your problem there. It just outputs to console.log and you can delete that.
Related
I'm creating a markdown editor and I need to check if neighbor characters are specific characters, then remove them, else append them.
For e.g I want to check selected-text, tow neighbor characters are **, then remove them, else append them around selected text.
I can get selected text using this approach:
function getSelection(elem) {
var selectedText;
if (document.selection != undefined) { // IE
elem.focus();
var sel = document.selection.createRange();
selectedText = sel.text;
} else if (elem.selectionStart != undefined) { // Firefox
var startPos = elem.selectionStart;
var endPos = elem.selectionEnd;
selectedText = elem.value.substring(startPos, endPos)
}
return selectedText;
}
$(document).on('mousedown', 'button', function(e) {
var selection = getSelection( $('#txtarea').get(0) );
alert(selection);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="txtarea">this is a test</textarea>
<button>Bold (toggle)</button>
Now I need when user clicks on that button, it checks if selected text is between ** like this **selectedtext**, then remove them like this selected text else append them like this **selectedtext**. How can I do that?
Before anything I would like to refer to all the markdown editors out there: https://www.google.de/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=javascript%20markdown%20library
So: do not try to reinvent the the wheel, and so on.
But for the sake of learning, my approach would look like this:
function toggleMarker(marker, el) {
var markerLength = marker.length;
var startPos, endPos, selection, range;
if (document.selection != undefined) { // IE
el.focus();
range = document.selection.createRange();
selection = range.text;
} else if (el.selectionStart != undefined) { // Firefox
startPos = el.selectionStart;
endPos = el.selectionEnd;
selection = el.value.substring(startPos, endPos);
}
if (!selection.length){
return;
}
if (el.value.substring(startPos-markerLength,startPos) === marker
&& el.value.substring(endPos,endPos+markerLength) === marker
){
el.value = el.value.substring(0,startPos-markerLength) +
selection +
el.value.substring(endPos+markerLength);
}
else{
el.value = el.value.substring(0,startPos) + marker +
selection + marker + el.value.substring(endPos);
}
}
$(document).on('mousedown', 'button', function(e) {
toggleMarker( $(this).data('marker'), $('#txtarea').get(0) ).text;
});
See it in action: https://jsfiddle.net/t4ro53v8/4/
The solution takes a very generic approach: the marker to toggle is set as a custom data attribute to make it easy to reuse the code.
The functionality is only implemented for the non-IE case. You will have to check, how to determine startPos and endPos for a range in IE.
In all other browsers:
the selection is identified
nothing is done if nothing is selected
sourroundings of the selection are checked against the given marker
if both markers are present, they get deleted
otherwise the markers are inserted
As a proof of concept this example works like a charm.
But there are some shortcomings:
How to distinguish between bold text(**) and italics(*)?
How to handle markers that just appear just on one side of the selection
What to do, if a marker is selected?
But that is for you to solve now ...
You could use regex to find the occurance of a ** ** pattern.This regex will help you find the pattern similar to what you have.
[*][*][a-z]*[*][*] .
Using the exec() method, will help you extract that particular text.
Check the length of this using .length, if it is 4, then there is nothing in between, and you can replace it with the new text surrounded by **,
"**"+ newtext+"**"
For removing the **, you can use the replace() method, where you replace ** with whitespace or so.
I have a form with a textarea (id = details).
Is there a way I can insert the HTML code for a line break (<br />) at the cursor position when hitting Enter within this textarea ?
I would only need this to get to work in IE.
<textarea class="input height120 elastic span12" name="details" id="details" onkeyup="countCharLimit(event)" onpaste="countCharLimit(event)"></textarea>
Try this:
$('textarea').keypress(function (e){
if(e.keyCode == 13){
$('textarea').val($('textarea').val()+"<br />");
}
});
You could try and fiddle with it here
EDIT: I realized this is adding a <br /> at the end only, after some more research, I found this solution:
$('textarea').keypress(function (e){
if(e.keyCode == 13){
e.preventDefault();
this.value = this.value.substring(0, this.selectionStart)+"<br />"+"\n";
}
});
Here is a fiddle for this one
Source (mostly): Insert text into textarea with jQuery
EDIT AGAIN: Looks like the OP wanted the text at the end to also be cleared, so I updated my code accordingly (for other's seeing this: check out the first edit of my relevant fiddle for the case you'd want to keep the remaining text).
you will need to find the caret position first as follow:
var caretPos = function() {
var el = $("#details").get(0);
var pos = 0;
if('selectionStart' in el) {
pos = el.selectionStart;
} else if('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
taken from :here
then you do:
var textofDetails = $("#details").val();
jQuery("#detail").val(textofDetails.substring(0, caretPos) + "<br/>" + textofDetails.substring(caretPos) );
Major EDIT:
no need for all the above ; your function will be
function replaceNewLine(){
jQuery("#detail").val().replace(/\\n/g, "<br />");
}
source: so - here
Yes, sure. It seems to be so, that you need keydown event processing and, possible, setTimeout 0 hack, look here: Why is setTimeout(fn, 0) sometimes useful?
I'm tiring to use Handsontable jQuery module with jQuery UI drag&drop functionality, but without success. I've fount some code with insertAtCaret function, but I have troubles using it with Handsontable.
I want to be able, to drag element from outside of Handsontable table, and drop it into cell. I know, that I have to update cell somehow...
Please help...
CODE:
$.fn.insertAtCaret = function (myValue) {
return this.each(function(){
//IE support
if (document.selection) {
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
}
//MOZILLA / NETSCAPE support
else if (this.selectionStart || this.selectionStart == '0') {
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)+ myValue+ this.value.substring(endPos,this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
});
};
My JSFiddle with source
The insertAtCaret code is not really what you need for this situation. You've already got a good handle on the required transaction - you need to use the ui.draggable element in the drop event to manually add some text to the correct cell. You just need a few final steps.
Now, one key piece of information is that Handsontable wants you to set cell data by coordinate, which means you need to know the column and row of the thing you want to set, not just have a javascript reference to the actual dom element. For that, we can use jQuery's index method.
Find out what cell the draggable has been dropped on.
Determine what that cell's column and row are.
Use Handsontable's setDataAtCell method to change the data.
Live Demo
$("#excel_table").droppable({
...
drop: function(event, ui) {
// Get a reference to the handsontable instance
var ht = $('#excel_table').handsontable('getInstance');
// Hide the helper, so that we can use .elementFromPoint
// to grab the item beneath the cursor by coordinate
ui.helper.hide();
var $destination = $(document.elementFromPoint(event.clientX, event.clientY));
// Grab the parent tr, then the parent tbody so that we
// can use their index to find the row and column of the
// destination object
var $tr = $destination.closest('tr');
var $tbody = $tr.closest('tbody');
var col = $tr.children().index($destination);
var row = $tbody.children().index($tr);
// Use the setDataAtCell method, which takes a row and
// col number, to adjust the data
ht.setDataAtCell(row, col, ui.draggable.text());
},
...
});
Assuming a regular <input type=text> text-box with data in it.
Is it possible to detect (via JavaScript) the position of the text-coursor inside that text-box?
I am able to detect an ARROW LEFT or ARROW RIGHT keydown event - but how to detect the cursor location?
Why I need this:
I have a dynamic text-box here: http://vidasp.net/tinydemos/dynamic-textbox.html
It works great, however there are two scenarios that I would like to fix:
when the cursor is at the beginning of the text-box and the user presses BACKSPACE
when the cursor is at the end of the text-box and the user presses DELETE
(In both cases, the text-box must contain data for the effect to be observable.)
I've done quite a lot of work on this. The following works in all major browsers (including IE 6) for text <input>s and <textarea>s and will work in all situations, including when there are leading and trailing spaces (which is where many solutions, including a-tools, fall down). There's some background to this code in this question: IE's document.selection.createRange doesn't include leading or trailing blank lines
You can also get the following as part of a jQuery input/textarea selection plug-in I've written that is as yet undocumented: http://code.google.com/p/rangyinputs/
function getInputSelection(el) {
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}
var el = document.getElementById("your_input");
var sel = getInputSelection(el);
alert(sel.start + ", " + sel.end);
yes it's possible.
It's even simpler if you use
http://plugins.jquery.com/project/a-tools
Good Luck :)
edit: please note that the cursor is msot often reffered to as "caret", just FYI ;)
I have these two codes -
new function($) {
$.fn.getCursorPosition = function() {
var pos = 0;
var el = $(this).get(0);
// IE Support
if (document.selection) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
// Firefox support
else if (el.selectionStart || el.selectionStart == '0')
pos = el.selectionStart;
return pos;
}
} (jQuery);
And
var element = document.getElementById('txtarr');
if( document.selection ){
// The current selection
var range = document.selection.createRange();
// We'll use this as a 'dummy'
var stored_range = range.duplicate();
// Select all text
stored_range.moveToElementText( element );
// Now move 'dummy' end point to end point of original range
stored_range.setEndPoint( 'EndToEnd', range );
// Now we can calculate start and end points
element.selectionStart = stored_range.text.length - range.text.length;
element.selectionEnd = element.selectionStart + range.text.length;
}
The first one is for getting the cursor position in a textarea and the second one is for determining the end of a textarea ,but they give the same result?
Where's the mistake?
I fix it.It's very simple :) .
I just replace the second code(for determining the end of the textarea) with:$("#txtarr").val().length(jQuery).#txtarr is the id of mine textarea.
Both pieces of code are doing the same thing in slightly different ways. Each is attempting to get the position of the caret or selection in a textarea (or text input), although the first only gets the start position of the selection while the second gets both the start and end positions.
Both have flaky inferences: the first assumes a browser featuring document.selection will support TextRange, while the second makes the same inference plus another that assumes a browser without support for document.selection will have support for selectionStart and selectionEnd properties of textareas. Neither will correctly handle line breaks in IE. For code that does that, see my answer here: How to get the start and end points of selection in text area?