1

If I have this HTML

<div class="comment-body">
[img]http://topnews.net.nz/images/YouTube-3.jpg[/img] random text here
</div>

<div class="comment-body">
[img]http://blog.brightcove.com/sites/all/uploads/FACEBOOK%20ICON.png[/img] random text here
</div>

how using jquery can I extract the value between [img] and [/img] and set it as a variable data-src2="" within an <img> element giving

<div class="comment-body">
<img src="samesrc" class="commentimg" data-src2="http://topnews.net.nz/images/YouTube-3.jpg"/> random text here
</div>

<div class="comment-body">
<img src="samesrc" class="commentimg" data-src2="http://blog.brightcove.com/sites/all/uploads/FACEBOOK%20ICON.png"/> random text here
</div>

I don't have anything to give for what I have tried as I don't have a clue how to extract the value between [img] and [/img]

but overall THIS is what I'm trying to achieve if it doesn't make sense!

Yusaf Khaliq
  • 3,333
  • 11
  • 42
  • 82

4 Answers4

10

Tested and now works (original version didn't iterate through all .comment-body elements, or find the substring() properly):

var divString, imgString;
$('.comment-body').each(
    function(){
        divString = $(this).text();
        imgString = divString.substring(divString.indexOf('[img]') + 5,divString.indexOf('[/img]'));
        console.log(imgString);
    });

JS Fiddle.


Edited because I got a little bit bored, and so turned the above into a more-generic function:

function findStringBetween(elem,bbTagStart,bbTagClose){
    var tag = bbTagStart;

    function impliedEndTag(tag){
        var impliedEnd = tag.replace(tag.substring(0,1),tag.substring(0,1) + '/');
        return impliedEnd;
    }

    var endTag = bbTagClose || impliedEndTag(tag);

    var divString = $(elem).text();
    var tagString = divString.substring(divString.indexOf('[img]') + tag.length,divString.indexOf('[/img'));
    return tagString;
}
$('.comment-body').each(
    function(){
        /* call with two, or three arguments (the third is the optional 'bbTagClose':
            1. elem = this, the DOM node,
            2. '[img]' = whatever bbCode thing you want to use (I'm not sure what's available),
            3. 'bbTagClose' = the end tag of the bbCode, assuming that the end-tag is the same as
                the opening tag, except with a '/' as the second character, the impliedEndTag() function
                will take care of it for you.
        */
        var elemString = findStringBetween(this,'[img]');
        $(this).replaceWith('<img src="' + elemString + '" class="commentimg" data-src2="'+ elemString +'"/>');
    });

JS Fiddle demo.


Edited following further questions from OP (in comments, below):

...the function adds an '' to every div with the class comment-body how can i only have the code applied to comment-body elements that contain [img]image src here[/img]

I've added a couple of sanity-checks, to ensure that the function returns false when the defined tag isn't found:

function findStringBetween(elem,bbTagStart,bbTagClose){
    var tag = bbTagStart;

    function impliedEndTag(tag){
        var impliedEnd = tag.replace(tag.substring(0,1),tag.substring(0,1) + '/');
        return impliedEnd;
    }

    var endTag = bbTagClose || impliedEndTag(tag);
    var divString = $(elem).text().trim(); // added .trim() to remove white-spaces

    if (divString.indexOf(tag) != -1){ // makes sure that the tag is within the string
        var tagString = divString.substring(divString.indexOf('[img]') + tag.length,divString.indexOf('[/img'));
        return tagString;
    }
    else { // if the tag variable is not within the string the function returns false
        return false;
    }
}
$('.comment-body').each(
    function(){
        /* call with two, or three arguments (the third is the optional 'bbTagClose':
            1. elem = this, the DOM node,
            2. '[img]' = whatever bbCode thing you want to use (I'm not sure what's available),
            3. 'bbTagClose' = the end tag of the bbCode, assuming that the end-tag is the same as
                the opening tag, except with a '/' as the second character, the impliedEndTag() function
                will take care of it for you.
        */
       var imgLink = findStringBetween(this,'[img]');
        if (imgLink){ // only if a value is set to the variable imgLink will the following occur
            $(this).replaceWith('<img src="' + imgLink + '" class="commentimg" data-src2="'+ imgLink+'"/>');
        }
    });

JS Fiddle demo.


Edited in response to further question from OP (in comments, below):

[Is] there a way of preventing it from removing the text in this example 'random text here'[?]

Yes, you can .append(), or .prepend() the image into the element, after first updating the text of the div, in the following code I've removed the [img]...[/img] string, to leave just the other text, inserted that text into the .comment-body element and then appended the img to that, instead of using replaceWith():

function findStringBetween(elem,bbTagStart,bbTagClose){
    var tag = bbTagStart;

    function impliedEndTag(tag){
        var impliedEnd = tag.replace(tag.substring(0,1),tag.substring(0,1) + '/');
        return impliedEnd;
    }

    var endTag = bbTagClose || impliedEndTag(tag);
    var divString = $(elem).text().trim();

    if (divString.indexOf(tag) != -1){
        var elemInfo = [];
        elemInfo.imgString = divString.substring(divString.indexOf(tag) + tag.length,divString.indexOf(endTag));
        elemInfo.text = divString.replace(tag + elemInfo.imgString + endTag, '');
        return elemInfo;
    }
    else {
        return false;
    }
}
$('.comment-body').each(
    function(){
        /* call with two, or three arguments (the third is the optional 'bbTagClose':
            1. elem = this, the DOM node,
            2. '[img]' = whatever bbCode thing you want to use (I'm not sure what's available),
            3. 'bbTagClose' = the end tag of the bbCode, assuming that the end-tag is the same as
                the opening tag, except with a '/' as the second character, the impliedEndTag() function
                will take care of it for you.
        */
       var elemInfo = findStringBetween(this,'[img]');
        if (elemInfo.imgString){
            // or .prepend() if you prefer
            $(this).text(elemInfo.text).append('<img src="' + elemInfo.imgString + '" class="commentimg" data-src2="'+ elemInfo.imgString +'"/>');
        }
    });

JS Fiddle demo.


References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • 1
    Sir, I don't know what in the _world_ you are talking about. All _I_ saw was a gust of wind. – Matt Ball Dec 04 '11 at 21:13
  • I have tried http://jsfiddle.net/yusaf/kYK7e/3/ it wont work could i please have a bit of guidance.please. – Yusaf Khaliq Dec 04 '11 at 21:25
  • I don't want to be fussy, but 'it wont work' isn't a great bug-report. In what way does it not work? – David Thomas Dec 04 '11 at 21:41
  • 2
    @Yusaf: David's code is working very well (+1 :o) ). You just need to use `tagString` to create the `` elements (like [here](http://jsfiddle.net/dzejkej/kYK7e/14/)). – kubetz Dec 04 '11 at 22:09
  • @dzejkej, thanks for amending the function to actually return the variable...I *knew* there was something left that I'd meant to do before posting it. Have a hearty, and grateful, +1 for your comment, sir! =) *Edited your amendments in* (Albeit I chose to replace with the image, rather than retain the `samesrc`...) – David Thomas Dec 04 '11 at 22:26
  • http://jsfiddle.net/kYK7e/34/ the function adds an '' to every div with the class comment-body how can i only have the code applied to comment-body elements that contain [img]image src here[/img] – Yusaf Khaliq Dec 04 '11 at 22:30
  • @Yusaf, see the updated answer; the final code block should work as you require. – David Thomas Dec 04 '11 at 22:48
  • is there a way of preventing it from removing the text in this example 'random text here' – Yusaf Khaliq Dec 04 '11 at 22:54
  • 1
    *Note to readers*: In case your code is calling `findStringBetween()` often, consider defining function `impliedEndTag()` outside of the `findStringBetween()`. When a function contains another function then everytime the "parent" function is called its "children" functions are created. So calling `findStringBetween()` 100 times means that `impliedEndTag()` is created 100 times. See **[this article](http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/)**. – kubetz Dec 04 '11 at 23:13
  • Yusaf, yes: see the latest edit and posted JS Fiddle. @dzejkej: good point; I'd forgotten about that. =/ – David Thomas Dec 04 '11 at 23:19
  • I promise you i have very little knowledge of jquery just the basics such as addclass removeclass etc, that is why i didn't try something if i had the knowledge on where to start i would have as you'll see in other more basic questions that i have asked but if you want to see what i was trying to achieve the whole time i have a link here http://jsfiddle.net/5RcEh/2/ it's almost in some ways similar to tumblr iamge posts on the dashboard – Yusaf Khaliq Dec 04 '11 at 23:36
  • 2
    I've added some reference materials to the end of the post, for you to read through. It can take a while to get comfortable with JavaScript, or even jQuery. Just ask the questions you have (once you've *tried* to research them) and, when you're able, start answering. I don't have time to look at your Fiddle now, but I'll try to remember to look tomorrow, after work. =) – David Thomas Dec 04 '11 at 23:51
  • 1
    @DavidThomas Great work, David! Nice extra bonus with all those reference materials :). – kubetz Dec 05 '11 at 00:15
  • @DavidThomas sorry to be a bug but what if there is more than 1 [img][/img] in a comment-body element i have tried .each for a funtion but it wont work http://jsfiddle.net/kYK7e/89/ – Yusaf Khaliq Dec 05 '11 at 14:02
2

Alternative answer to the one wrote by David Thomas.

Another way how to implement this code is to use regular expressions.

// inputText - input text that contains tags
// tagName - name of the tag we want to replace
// tagReplace - replacement for the tag, "$1" will get replaced by content of the tag
function replaceText(inputText, tagName, tagReplace) {
  var regExp = new RegExp('\\[' + tagName+ '\\]([^\\[]*)\\[\/' + tagName + '\\]', 'g');
  return inputText.replace(regExp, tagReplace);
}

$('.comment-body').each(function() {
  var $this = $(this);
  var replacedText = replaceText($this.text(), 'img', '<img src="$1" \/>');
  $this.html(replacedText);
});

This implementation will also replace multiple tags within the comment.

See THIS code snippet.

Note 1:

When implementing this code in real environment please consider pre-creating regular expression for all handled tag names outside replaceText() so regExp won't be created everytime replaceText() is called.

Note 2:

To get the exact output as in the question change:

  var replacedText = replaceText($this.text(), 'img', '<img src="$1" \/>');

to

  var replacedText = replaceText($this.text(), 'img', '<img src="samesrc" class="commentimg" data-src2="$1" \/>');
kubetz
  • 8,485
  • 1
  • 22
  • 27
  • how can you alter this so it works alongside the YouTube tags i have because they also use $1 http://jsfiddle.net/x7N7S/11/ – Yusaf Khaliq Dec 05 '11 at 13:20
  • @Yusaf: I recommend you to study a bit and experiment with the code so you will be able to modify it by yourself. If you will still have trouble, **create a new question**. Use comments only to discuss the concrete answer for a concrete question and not for other purposes. FYI: Code in my answer will put whole youtube link to `$1`. To solve your issue you need to either modify the regexp to extract only the `?watch=` part and not youtube link or insert only `?watch=thisPart` between the tags (more general solution): see **[THIS](http://jsfiddle.net/dzejkej/Y8TG7/11/)**. – kubetz Dec 05 '11 at 13:41
  • thankyou, i have tried stuff but they're useless, i will post links for failures from now, sorry. – Yusaf Khaliq Dec 05 '11 at 13:44
  • 2
    @Yusaf: Glad to help :). Sorry if it sounded rude, but creating a question helps other people to find same problems more easily, people helping you have better tools (like code blocks, ability to edit after more than 5 minutes, etc.) and they can get some extra rep as a bonus :). – kubetz Dec 05 '11 at 13:49
  • I have created a solution to the [youtube][/youtube] and [img][/img] problem i was having, dzejkej and David Thomas you have been brilliant thankyou very much. – Yusaf Khaliq Dec 05 '11 at 16:50
1

This function finds any given bbcodes in any string and if you want, you can configure it for replacing or extract content as array from those bbcodes.

//search str 
var search_str = "I love this [img]question.png[/img] Flowers, and [img]answer_1-1.png[/img] you say is that [img]answer_2-1.png[/img] good Point."
//using example
var str = bbcode_search_and_replace($('#search_str').text(),"[img]","[/img]");
$('#search_str').html(str);

function bbcode_search_and_replace(search_str, bb_opening_tag, bb_closing_tag) {
            //search str length
           var sLength = String(search_str).length;
           //bbcode opening tag length
           var fPart_length = String(bb_opening_tag).length;
           //bbcode closing tag length
           var ePart_length = String(bb_closing_tag).length;
           //position index for opening tag 
           var start_idx = 0;
           //position index for closing tag 
           var end_idx = 0; 
           //searching index for opening tag
           var pos_sIdx = 0;
           //position index for closing tag
           var pos_eIdx = 0;
           //var replacement = '[image]';
           var arr = [];
           var idx = 0;           

           //loop
           while(start_idx !== -1) {
               arr[idx] = {};                  

               start_idx = String(search_str).indexOf(bb_opening_tag,pos_sIdx);
               //check for ending
               if(start_idx === -1) {
                   //if exist, last str after closing tag
                   if(idx > 0) arr[idx]['str'] = search_str.substring(pos_sIdx);
                   console.log("arr[idx]['str'] = " + arr[idx]['str']);
                   break;
               }
               //end position index
               pos_eIdx = start_idx + fPart_length;
               end_idx = String(search_str).indexOf(bb_closing_tag,pos_eIdx);                   
               //save str inside bbtags
               arr[idx]['str'] = search_str.substring(pos_sIdx, start_idx);
               console.log("arr[idx]['str'] = " + arr[idx]['str']);
               arr[idx]['src'] =  "<img src = 'img/" + search_str.substring(start_idx + fPart_length, end_idx) + "' />";
               console.log("arr[idx]['src'] = " + arr[idx]['src']);
               arr[idx]['pos_start'] = start_idx + fPart_length;
               arr[idx]['pos_end'] = end_idx;                                

               //Update array and start pos indexes
               idx++;
               pos_sIdx = end_idx + ePart_length;                
          }

           var k = 0;
           var str = "";
           while(k < arr.length) {
               if(arr[k]['src'] === undefined) arr[k]['src'] = "";
               str += arr[k]['str'] + arr[k]['src'];
               k++;
           }

           return str;
        }  
Amanzhol
  • 11
  • 1
1

Use JavaScript match() function, very easy to use

Like if you have a string "The quick brown fox jumps over the lazy dog."

& you need the text just between "quick" and "lazy"

Use below

<script type="text/javascript">
   var myStr = "The quick brown fox jumps over the lazy dog.";
   var subStr = myStr.match("quick(.*)lazy");
   alert(subStr[1]);
</script>

Hope it helps !!

Mahesh Yadav
  • 2,416
  • 20
  • 23