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!

8
  • 1
    No need for jQuery, just a plain jane regex! Commented Dec 4, 2011 at 21:05
  • 1
    So, you want a BBCode parser? Commented Dec 4, 2011 at 21:06
  • @Rocket something to that effect yes, it makes things easier! Commented Dec 4, 2011 at 21:07
  • 1
    What have you tried so far? Show some effort, please. Also: stackoverflow.com/questions/1843320/… Commented Dec 4, 2011 at 21:07
  • I wish I could upvote a comment 10 times Commented Dec 4, 2011 at 21:08

4 Answers 4

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:

Sign up to request clarification or add additional context in comments.

14 Comments

Sir, I don't know what in the world you are talking about. All I saw was a gust of wind.
@Yusaf: David's code is working very well (+1 :o) ). You just need to use tagString to create the <img> elements (like here).
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.
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. =)
@DavidThomas Great work, David! Nice extra bonus with all those reference materials :).
|
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" \/>');

5 Comments

how can you alter this so it works alongside the YouTube tags i have because they also use $1 jsfiddle.net/x7N7S/11
@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.
thankyou, i have tried stuff but they're useless, i will post links for failures from now, sorry.
@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 :).
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.
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;
        }  

Comments

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 !!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.