Reputation: 2272
I am currently having an annoying little problem. I am making my own BBCode editor, and coding the parser as well.
Now the problem is lets say the user enters this in the text area:
Hello my name is Michael Jones.
What is your name?
If the user highlights the first 'name', it will then edit that selected 'name' in the first line. The problem is though if the user selects the 'name' in the second sentence and tries to edit it, it will edit the first 'name' instead.
I have figured out that when using .replace
it replaces the first word found. So my question is how do I replace the correct match of the word? I am very unsure of what to do! :( Here is my code:
function getInputSelection(item){
if(typeof item != "undefined"){
start = item[0].selectionStart;
end = item[0].selectionEnd;
return item.val().substring(start, end);
}
else{
return '';
}
}
$('button[type="button"]').click(function() {
var textareavalue = $('#textareainput').val();
var highlightedvalue = getInputSelection($('#textareainput'));
var updatedvalue = '['+$(this).attr('name')+']' + highlightedvalue + '[/'+$(this).attr('name')+']';
textareavalue = textareavalue.replace(highlightedvalue, updatedvalue);
$('#textareainput').val(textareavalue)
});
$('button[type="button"], #textareainput').on('click keyup',function(){
$('#posttextareadisplay').text($('#textareainput').val());
var replacebbcode = $('#posttextareadisplay').html().replace(/(\[((\/?)(b|i|u|s|sup|sub|hr))\])/gi, '<$2>')
.replace(/(\[((align=)(left|center|right|justify))\])/gi, '<div align="$4">')
.replace(/(\[((color=#)([0-9a-fA-F]{1,}))\])/gi, '<div style="color:#$4">')
.replace(/(\[((size=)(1|2|3|4|5|6))\])/gi, '<font size="$4">')
.replace(/(\[((\/)(size))\])/gi, '</font>')
.replace(/(\[((\/)(align|color|size))\])/gi, '</div>');
$('#posttextareadisplay').html(replacebbcode);
});
If you would like more information, or more understanding of the question, please comment! :) Thank You, please help.
Upvotes: 0
Views: 97
Reputation: 6693
So, first let's take a look at what you ARE doing. When the button is clicked, you:
When you lay it out that way, the redundant part becomes obvious. Rather than turning the indexes into a search string and then trying to find it...replace using the indexes! That way, there's no ambiguity.
This other answer is relevant: Is there a splice method for strings?
Array.prototype.slice()
removes a range of items from an array and, optionally, puts something else in their place. That's what we want here. Unfortunately, there's no native String.prototype.slice()
. Fortunately, it's easy to implement one. In that other answer, they did it like this:
function spliceSlice(str, index, count, add) {
return str.slice(0, index) + (add || "") + str.slice(index + count);
}
To explain that, take a look at the documentation for String.prototype.slice()
, which sounds almost like splice()
, but isn't.
They shaped the parameters that way to match Array.slice()
, but for your purposes, it would be more convenient to do this:
function stringSplice(str, startIndex, endIndex, newText) {
return str.slice(0, startIndex) + (newText|| "") + str.slice(endIndex);
}
What we're doing here is using slice()
to get all of the text BEFORE the selected area, and all of the text AFTER the selected area, and then sticking the replacement text in between them.
Then you'll want something like this:
var textareavalue = $('#textareainput').val();
var selectionStart = $('#textareainput')[0].selectionStart;
var selectionEnd = $('#textareainput')[0].selectionEnd;
textareavalue = stringSplice(textareavalue, selectionStart, selectionEnd, updatedvalue);
$('#textareainput').val(textareavalue)
Upvotes: 1