4

I need to manipulate a string-variable with JavaScript, which has some html-content. I want to search for some elements, change them and wrap these elements with another div-container.

How can I get this:

var myArr = ['Foo', 'Bar'];
var contenthtml = "<p>Foo</p>
  <p>Lorem ipsum dolor sit amet</p>
  <p>Lorem <b>ipsum</b> dolor sit amet</p>
  <p>Lorem ipsum dolor sit amet</p>
  <p>Bar</p>
  <p>Lorem ipsum dolor sit amet</p>";

to this:

contenthtml = "<div class='foo'><h1>Foo</h1>
  <p>Lorem ipsum dolor sit amet</p>
  <p>Lorem <b>ipsum</b> dolor sit amet</p>
  <p>Lorem ipsum dolor sit amet</p></div>
  <div class='bar'><h1>Bar</h1>
  <p>Lorem ipsum dolor sit amet</p></div>";
9
  • Regular expressions are possibly what you are after (though they can cause as much trouble as they can help...) Commented Feb 14, 2014 at 20:52
  • jQuery has a number of useful functions for operating on blocks of DOM elements, wrapping them in other elements, etc. Commented Feb 14, 2014 at 20:54
  • @Barmar But I do not know how to use JQuery, as the html-code is in a variable. It is not part of the DOM. So I have these to variables (string and array) and need to get the manipulated string. Commented Feb 14, 2014 at 21:02
  • jQuery can convert an HTML string into disconnected DOM elements, manipulate it, and then convert it back to a string. If you learn jQuery, this will be much easier than trying to do this with regexp. Commented Feb 14, 2014 at 21:04
  • @Barmer I really like JQuery much, so I'm very interested in a JQuery-solution. Can you give me a short example how to convert the string in a "disconnected" DOM? Commented Feb 14, 2014 at 21:06

3 Answers 3

1

You can use a regular expression (similar to my other answer at https://stackoverflow.com/a/21803683/3210837):

var keywordsRegEx = keywords.map(function(x){return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');}).join('|');
var result = str.replace(new RegExp('<p>(' + keywordsRegEx + ')</p>\r\n((?:[ \t]*<p>(?:(?!' + keywordsRegEx + ').)*</p>(?:\r\n)?)*)', 'mgi'), '<div><h1 class="$1">$1</h1>\r\n$2</div>\r\n');

See http://jsfiddle.net/ncu43/1/ for a full example.

What the regular expression does is it matches <p>, one of the keywords, </p>, and then a paragraph (not containing one of the keywords) zero or more times.

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

Comments

1

I used some DOM to solve this problem. For those who prefer a DOM solution, rather than RegExp:

Append elements in a variable instead of a temporary DOM

3 Comments

I'm not sure what you mean. You asked to change a string into another string, as far as I could see.
Yes. But it is a html string. So isn't a dom-manipulation the better way?
I suppose so, but a regular expression is generally faster that DOM manipulation as the RegExp is compiled. Can you include the code you used to achieve it, please?
0

This would be a little bit easier with straight-up DOM replacement/wrapping (in fact, I wrote such a solution but re-wrote it when I saw your comment saying you needed string input), but here's a solution using just a string as input:

var myArr = ['Foo', 'Bar'];
var contenthtml = '<p>Foo</p>\n'
    + '<p>Lorem ipsum dolor sit amet</p>\n'
    + '<p>Lorem <b>ipsum</b> dolor sit amet</p>\n'
    + '<p>Lorem ipsum dolor sit amet</p>\n'
    + '<p>Bar</p>\n'
    + '<p>Lorem ipsum dolor sit amet</p>';
var elements = $.parseHTML(contenthtml);
var tmp = '';
$.each(elements, function(index, element) {
    $.each(myArr, function(i, e) {
        if (element.innerHTML == e) {
            elements[index] = $('<h1>' + e + '</h1>').get(0);
            return;
        }
    });
    if (elements[index].outerHTML) {
        tmp += elements[index].outerHTML + '\n';
    }
});
contenthtml = '<div class="foo">' + tmp + '</div>';
console.log(contenthtml);

jsfiddle

1 Comment

Thank you very much. But there is still a problem. As the elements from the array will be modified to a h1-element, all elements from one h1-element to the next element should be wraped in a div-container. So in that example there should be two div-container: the first one from the h1-foo to h1-bar and the second from h1-bar to the next h1-element (in this case to the end)

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.