exionyte
exionyte

Reputation: 23

jQuery replace Start and End tag in html document

I have the following jQuery snippet which should replace a code such as [Button] Text Here [/Button] into something like:

<a class="button">Text Here</a>

The javascript I have is the following:

$(document).ready(function() {

    var buttonStart = $("body").html().replace(/\[Button\]*/ig,'<a class="button">');
    $("body").html(buttonStart);

    var buttonEnd = $("body").html().replace(/\[\/Button\]*/ig,'</a>');
    $("body").html(buttonEnd);

});

The problem I am having is that it keeps replacing other elements on my page which have nothing to do with the Tags [Button] [/Button]. For insance the following:

  <div id="MiddleBarLeft"></div>

Also gets replaced into

  <a class="button"><div id="MiddleBarLeft"></div></a>

Shouldn't the Regex I have above just look for [Button] and [/Button] Tags?

Also, is there any other efficient way to go about this?

Thanks

=====================

Update.. this is my entire HTML file which replaces elements that have nothing to do with what I want to replace

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>

    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script type='text/javascript'>
    $(document).ready(function() {

        var buttonStart = $("body").html().replace(/\[Button\]/ig,'<a class="button">');
        $("body").html(buttonStart);

        var buttonEnd = $("body").html().replace(/\[\/Button\]/ig,'</a>');
        $("body").html(buttonEnd);

    });
    </script>


    <style>
    li{ 
    list-style:none;
        padding-top:10px;
        padding-bottom:10px;}   

    .button, .button:visited {
        background: #222 url(overlay.png) repeat-x; 
        display: inline-block; 
        padding: 5px 10px 6px; 
        color: #fff; 
        text-decoration: none;
        -moz-border-radius: 6px; 
        -webkit-border-radius: 6px;
        -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6);
        -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6);
        text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
        border-bottom: 1px solid rgba(0,0,0,0.25);
        position: relative;
        cursor: pointer
    }
    </style> 



    </head> 
        <body> 

     <div>          
           <ul>
            <li>[Button]Test[/Button]</li>
            <li></li>
            <li>Sample Text</li>
            </ul>
     </div>       


        </body> 
    </html> 

Upvotes: 2

Views: 1916

Answers (4)

eithed
eithed

Reputation: 4339

The problem stems from the way the replacement occurs - please consider the following fiddle: http://jsfiddle.net/GYrYa/

As you can see there are two buttons in the end, even though there's only one [Button][/Button] statement - it's because first you're replacing [Button] with <a class='button'> which creates an unmatched tag. This causes an </a> to be added at the end. Then you're replacing [/Button] with </a>, which creates another unmatched tag - this time <a>, at the end.

A better solution would be this: http://jsfiddle.net/GYrYa/1/

EDIT: http://jsfiddle.net/GYrYa/2/ to omit script tag matching

EDIT 2: http://jsfiddle.net/GYrYa/5/ - final solution, incorporating @Rain Diao non-greedy matching

EDIT 3: Added performance test cases: http://jsperf.com/eithed-rsc3, please read the discussion below @Rain Diao's answer for the genesis of it

Upvotes: 1

Rain Diao
Rain Diao

Reputation: 926

In actually, I did a quick testing, but cannot reproduce your problem. Please offer me more details, like an example.

two tips, ccouldimprove the performance:

  1. remove the star in your RegExp. I think it was unneccessary.

  2. call $('body').html(buttonReplaced) only once:

    var buttonReplaced = $("body").html()
                         .replace(/\[Button\]/ig,'<a class="button">')
                         .replace(/\[\/Button\]/ig,'</a>');
    $('body').html(buttonReplaced);
    
  3. another solution:

    var buttonReplaced= $('body').html().replace(/\[Button\](.*?)\[\/Button\]/gi, '<a class="button">$1</a>');
    $('body').html(buttonReplaced);
    

Upvotes: 1

Techmonk
Techmonk

Reputation: 1469

Use + instead of a star in your regex. As the first will match nothing as well

$(document).ready(function() {

    var buttonStart = $("body").html().replace(/\[Button\]/ig,'<a class="button">');
    $("body").html(buttonStart);

    var buttonEnd = $("body").html().replace(/\[\/Button\]/ig,'</a>');
    $("body").html(buttonEnd);

});

Upvotes: 0

Stiger
Stiger

Reputation: 1199

I thinks this code $("body").html(buttonEnd); will replace buttonStart. Mybe you shout try append() method, like this: $("body").append(buttonEnd);

Upvotes: 0

Related Questions