Kieran Quinn
Kieran Quinn

Reputation: 1115

javascript .replace width tag

Looking for help with a javascript reg ex replacement. What I need, is to replace all instances of

width="100">

With

style="width: 100px;"

But the actual px value is variable which is what is causing issues for me. I know reg expression is the way to go but I dont quite understand it.

This is a similar question but doesn't solve the issue for me: JavaScript Regex Replace Width Attribute Matching

The reason this is a problem is because of the HTML generated by TinyMce...

Upvotes: 0

Views: 1995

Answers (2)

MildlySerious
MildlySerious

Reputation: 9180

My first thought also was to work with the DOM instead of using RegEx. Instead of iterating over all the elements, we could just use querySelector, which supports attribute selectors.

var html = '<img src="//placehold.it/100x100" alt="" style="100px;">'+
           '<img src="//placehold.it/120x120" alt="" width="120" style="border: 2px solid steelblue;">'+
           '<img src="//placehold.it/140x140" alt="" width="140">',
    wrap = document.createElement('div'),
    nodes;

wrap.innerHTML = html;

nodes = wrap.querySelectorAll('[width]');

Array.prototype.forEach.call(nodes, function(el) {
    var width = el.getAttribute('width');
    if(width) {
        el.removeAttribute('width');
        el.style.width = width+'px';
    }
});

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1075199

Two options:

  • Using a regular expression

  • Parsing the HTML and working with the DOM (preferred)

Using a regular expression

The expression is fairly straightforward:

str = str.replace(/\bwidth="(\d+)"/g, 'style="width: $1px"');

The $1 in the replacement string is filled in with the content of the first capture group.

Example:

var str = '<div width="100">Stuff here</div><div width="240">More stuff here</div>';
display("Before: '" + str + "'");
str = str.replace(/\bwidth="(\d+)"/g, 'style="width: $1px"');
display("After: '" + str + "'");

function display(msg) {
  document.body.insertAdjacentHTML(
    "beforeend",
    "<p>" +
    String(msg)
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;") +
    "</p>"
  );
}

But note that that will:

  1. Replace width="nnn" everywhere in the string, even if not inside a start tag

  2. End up adding a second style attribute to a tag that already has one

If that's okay, great; if not, you might want to parse the HTML, process the resulting parsed DOM nodes, and then serialize it again.

Parsing the HTML and working with the DOM

A better option is to parse the HTML and work with the DOM. You've said that the HTML will be for a div, so we don't have to worry about things like standalone table cells, etc.

Here's a simple parsing and updating example:

var str = '<div width="100">Stuff here</div><div width="240">More stuff here</div>';
var div = document.createElement('div');
div.innerHTML = str;
update(div.childNodes);
display("Before: '" + str + "'");
str = div.innerHTML;
display("After: '" + str + "'");

function update(nodes) {
  Array.prototype.forEach.call(nodes, function(node) {
    var width;
    if (node.nodeType === 1) { // An element
      width = node.getAttribute("width");
      if (width) {
        node.removeAttribute("width");
        node.style.width = width + "px";
      }
      update(node.childNodes);
    }
  });
}

function display(msg) {
  document.body.insertAdjacentHTML(
    "beforeend",
    "<p>" +
    String(msg)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;") +
    "</p>"
  );
}

Upvotes: 3

Related Questions