0

I have some markup in JS as follows:

<div class="col-sm-4">
    <span id="some-media" class="media">Text</span>
</div>

I would like to select the class attribute of the span and prepend its value with lets say the characters: "::". So after the regex replace i would end up with:

<div class="col-sm-4">
    <span id="some-media" class="::media">Text</span>
</div>

EDIT: Note that the order of the attributes in the HTML element is variable so my span attributes could very well have different order like so:

<div class="col-sm-4">
    <span class="::media" id="some-media" >Text</span>
</div>
5
  • 3
    Is there any specific reason you have to use regex for this? Commented Sep 13, 2017 at 15:09
  • @thebluefox ive managed to select the attribute with the following regex so far: <span[^>]+class\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>. However i havent been able to prepend the characters to the class value. Commented Sep 13, 2017 at 15:12
  • @Psidom do you any other alternative for accomplishing this? I dont want to include a parser just to solve a small problem like this. Commented Sep 13, 2017 at 15:25
  • Take a look at this answer. BTW, what's wrong with a parser? Commented Sep 13, 2017 at 15:28
  • Take a look at the second answer to the question you posted as well. I think a parser for solving such a trivial problem is overkill. Commented Sep 13, 2017 at 15:33

5 Answers 5

3

You got a regex solution, this is a DOMmy one:

var html = `<div class="col-sm-4">
    <span id="some-media" class="media">Text</span>
</div>`
var doc = (new DOMParser()).parseFromString(html, "text/html");
var el = doc.getElementsByTagName('span')[0];
el.setAttribute('class', '::' + el.className);
console.log(
  doc.getElementsByClassName('::media').length > 0 // check if modification's done
);

Since you have no way except Regular Expressions this can be considered as a workaround:

(<span[^>]*class=.)([^'"]+)

JS:

var html = `<div class="col-sm-4">
    <span id="some-media" class="media">Text</span>
</div>
<span class="media" id="some-media">Text</span>
`;

console.log(
    html.replace(/(<span[^>]*class=.)([^'"]+)/g, `$1::$2`)
);

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

5 Comments

I am using nodejs to solve this problem sorry should have mentioned in my question so i dont have access to DOMParser.
What could be the selector? .col-sm-4 span or span alone?
I dont understand the question?
I mean how much big your HTML document would be and what are the rules to match that span? What if that span is a direct child of body? Should it be selected for later modification?
I just want to match all the spans in the markup, there is no other specific rule for matching.
0

This isn't using regex, but you can do it like this in vanilla JavaScript:

const el = document.getElementsByClassName('media')[0];
el.className = '::' + el.className;

Or in jQuery:

const $el = $('div span.media');
$el.attr('class', '::' + $el.attr('class'));

Hope this helps.

Comments

0

Don't parse html with regex, use DocumentFragment (or DOMParser) object instead:

var html_str = '<div class="col-sm-4"><span class="media">Text</span></div>',
    df = document.createRange().createContextualFragment(html_str),
    span = df.querySelector('span');
    
span.setAttribute('class', '::' + span.getAttribute('class'));
console.log(df.querySelector('div').outerHTML);

1 Comment

Dont have access to either of those in Node.
0

I think this is what you're after:

var test = $("#some-media")[0].outerHTML();
var test2 = '<div id="some-media" class="media">Text</div>'

if(/span/.test(test)) //Valid as contains 'span'
    alert(test.replace(/(class=")/g, "$1::"));

 if(/span/.test(test2)) //Not valid
    alert(test.replace(/(class=")/g, "$1::"));

5 Comments

I believe this will prepend all class attribute values in the markup with the characters. I am only looking to prepend if it is an attribute of a particular html element (in this case a span).
this wont work if the span is nested under the div which is my usecase.
@asulaiman Why won't it? how are you getting your span object? See my updated answer. You can use outerHTML() to get the html of an object
The markup is encapsulated in a string that i am trying to parse. This is on node it isnt in a web browser.
My bad, missed the node part
0

Since the order differs, writing a regex that captures all possible combinations of syntax might be rather difficult.

So we'd need a full list of rules the span follows so we can identify that span? Got some more info about if the span occurs in a longer HTML string? Or is the string this span and this span only?

An alternative would be to use one of the several node DOM modules available, so you can work with HTML nodes and be able to use any of the above solutions to make the problem simpler.

But since you're using node:

1) Are you using any templating engines? If so, why not rerender the entire template?

2) Why does the class name have to change on the server side? Isn't there a workaround on the clientside where you do have access to the DOM natively? Or if it's just to add styling, why not add another css file that overwrites the styling of spans with className 'media'?

3) If all of the above is not applicable and it;s a trivial problem like you say, what error di you get using a simple replace?

strHTML.replace( 'class="media"', 'class="::media"' )

or if it has to be regex:

strHTML.replace( /class=\"(.*)\"/, 'class=\"::$1\"' );

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.