0

I've looked through the suggested SO questions and none of them suite this. Basically I have a little form textarea that can have BBCODE in it. That could have something like this:

[url=http://www.derp.com/]link[/url]

[url=http://www.derp.com/435]link[/url]

Now Everything works fine when highlighting(selecting) a link. It runs through this function

selection_get: function(container) {
    var editor = $(container);

    var u = editor.val();
    var start = editor.get(0).selectionStart;
    var end = editor.get(0).selectionEnd;

    return [u.substring(0, start), u.substring(end), u.substring(start, end)];
}

Which grabs the selected text. My issue is if a user clicks within the [url][/url] tags (not selecting anything), I'd like to get that specific url bbcode.

I've tried something like this so far (Note: regular expressions is one of my weaknesses! :-():

var text = AMI_editor.selection_get('form#new-brand textarea');

// check if text has regex
if (text[2] == '' || text[2] == null) {
    // find the closest [url]
    var find = text[0] + text[1];
    var findurl = find.match(/\[url=(.*?)\](.*?)\[\/url\]/gi);
    console.log(findurl);
}

Now for the above case with 2 links it returns an array like this:

["[url=http://www.derp.com/derparoo/dering/?q=derp&me=awesomp]y[/url]", "[url=http://www.derp.com/derparoo/dering/?q=derp&me=awesomp]dwd[/url]"]

Now I thought about using something like this, yet don't know how I'd implement it:

function getCursorPos(input) {
    if ("selectionStart" in input && document.activeElement == input) {
        return {
            start: input.selectionStart,
            end: input.selectionEnd
        };
    }
    else if (input.createTextRange) {
        var sel = document.selection.createRange();
        if (sel.parentElement() === input) {
            var rng = input.createTextRange();
            rng.moveToBookmark(sel.getBookmark());
            for (var len = 0; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1)) {
                len++;
            }
            rng.setEndPoint("StartToStart", input.createTextRange());
            for (var pos = { start: 0, end: len }; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1)) {
                pos.start++;
                pos.end++;
            }
            return pos;
        }
    }
    return -1;
}

function setCursorPos(input, start, end) {
    if (arguments.length < 3) end = start;
    if ("selectionStart" in input) {
        setTimeout(function() {
            input.selectionStart = start;
            input.selectionEnd = end;
        }, 1);
    }
    else if (input.createTextRange) {
        var rng = input.createTextRange();
        rng.moveStart("character", start);
        rng.collapse();
        rng.moveEnd("character", end - start);
        rng.select();
    }
}

$(function() {
    $(":input.getPos").on("keyup click", function(e) {
        var pos = getCursorPos(this);
        $(this).siblings(".posStart").val(pos.start);
        $(this).siblings(".posEnd").val(pos.end);
    }).siblings("input").keydown(function(e){
        if (e.keyCode == 13){
            $(this).siblings("button").click();
            e.preventDefault();
        }
    });
    $("button").click(function(e) {
        var par = $(this).parent();
        setCursorPos(par.find(":input.getPos")[0], +par.find(".posStart").val(), +par.find(".posEnd").val());
    });
});

TL;DR

Find the closest instance of said bbcode ([url][/url]) to the cursor point. Examples:

I'll use | as the cursor point in the examples below:

[url=http://www.google.com/]Go|ogle[/url]

or something like:

[url=http://www.yahoo.com/]Yahoo[/url] and [url=http://www.google.com/]Google[/url]|
Community
  • 1
  • 1
Darren
  • 13,050
  • 4
  • 41
  • 79

1 Answers1

0

I'll post you a code i've used a lot in my PHP workings. it works like a charm so i'm guessing it should help you out. just translate it to javascript it shouldn't be that hard :D

<?php

/* Simple PHP BBCode Parser function */

//BBCode Parser function

function showBBcodes($text) {

// BBcode array
$find = array(
'~\[b\](.*?)\[/b\]~s',
'~\[i\](.*?)\[/i\]~s',
'~\[u\](.*?)\[/u\]~s',
'~\[quote\](.*?)\[/quote\]~s',
'~\[size=(.*?)\](.*?)\[/size\]~s',
'~\[color=(.*?)\](.*?)\[/color\]~s',
'~\[url\]((?:ftp|https?)://.*?)\[/url\]~s',
'~\[img\](https?://.*?\.(?:jpg|jpeg|gif|png|bmp))\[/img\]~s'
);

// HTML tags to replace BBcode
$replace = array(
'<b>$1</b>',
'<i>$1</i>',
'<span style="text-decoration:underline;">$1</span>',
'<pre>$1</'.'pre>',
'<span style="font-size:$1px;">$2</span>',
'<span style="color:$1;">$2</span>',
'<a href="$1">$1</a>',
'<img src="$1" alt="" />'
);

// Replacing the BBcodes with corresponding HTML tags
return preg_replace($find,$replace,$text);
}

// How to use the above function:

$bbtext = "This is [b]bold[/b] and this is [u]underlined[/u] and this is in [i]italics[/i] with a [color=red] red color[/color]";
$htmltext = showBBcodes($bbtext);
echo $htmltext;

?>

Juan Vilar
  • 435
  • 3
  • 11
  • Hi mate, unfortunately that's not what I'm looking for. I need to get the closest occurrence of a bbcode to the cursor point :( – Darren Jun 12 '14 at 00:44