views:

56

answers:

2

Would like to use jQuery to:

  1. select any punctuation marks (meaning . , ; : ' " “ ” ‘ ’ etc.) that occur directly before and after any links and then
  2. wrap the punctuation marks in spans.

Hence this:

<div id="mydiv">
  Lorem ipsum
  <a href="#">dolor sit amet</a>,
  consectetur
  &ldquo;<a href="#">adipisicing elit</a>&rdquo;.
</div>

to become this:

<div id="mydiv">
  Lorem ipsum
  <a href="#">dolor sit amet</a><span>,</span>
  consectetur
  <span>&ldquo;</span><a href="#">adipisicing elit</a><span>&rdquo;.</span>
</div>

(BTW, &ldquo and &rdquo; are quotation marks.)

The content in the div is not fixed. There may also be instances where there's more than one punctuation mark adjacent to a link (as in the above, &rdquo;. to become <span>&rdquo;.</span>)

Would really appreciate any help!!


Sorta similar (but not quite) to this question with regards to selecting text nodes? http://stackoverflow.com/questions/2742223/using-jquery-how-to-modify-text-outside-of-tags/2742348#2742348

+2  A: 

This seems to work:

Try it out: http://jsfiddle.net/GutKg/1/

var $div = $('#mydiv');

var html = $div.html();

html = html.replace(/([^\s\w]+)<a/g, '<span>$1</span><a')
           .replace(/<\/a>([^\s\w]+)/g, '</a><span>$1</span>');

$div.html( html );​

EDIT: Updated to exclude alphanumeric characters adjacent to the tags.

patrick dw
A: 

Extending my question somewhat: what if instead of a lone div with an id, there were many instances of the div (say with the class mydiv) throughout the page?

<div class="mydiv">
  Lorem ipsum
  <a href="#">dolor sit amet</a>,
  consectetur
  &ldquo;<a href="#">adipisicing elit</a>&rdquo;.
</div>
<div class="mydiv">
  Ei vel <a href="#">velit mollis vivendo</a>.
</div>

Cobbled something together off patrick's solution:

$('.mydiv').each(function () {
  html = $(this).html().replace(/([^\s\w]+)<a/g, '<span>$1</span><a')
                       .replace(/<\/a>([^\s\w]+)/g, '</a><span>$1</span>');
  $(this).html( html );
});

It works -- http://jsfiddle.net/ZEC3X/ -- but I dunno, is it the most efficient/logical way to go about doing it?

qwer0o
That would be correct. You're doing the exact same thing only over an iteration of elements. Regarding efficiency/logic, what's on your mind? Do you mean in terms of the iteration? or the regex?
patrick dw
I believe the javascript is essentially saying to the browser: 1) select all elements with the class `mydiv`, then 2) do a regex replacement for the html within each matched element. This part about the regex replacement for **each matched element** feels like quite a bit of heavy lifting being done? Maybe I'm assuming too much/thinking about this all wrong. Anyway. According to http://stackoverflow.com/questions/415629/most-efficient-way-to-find-elements-in-jquery perhaps `div.mydiv` would be just a bit better than just `.mydiv`...
qwer0o
@qwer0o - Doing `div.mydiv` instead of `.mydiv` speeds up the selector for IE. This is because Safari, Firefox, etc. have as part of the native API a method called `getElementsByClassName` but IE does not. Because IE does not, it has to get *all* elements, and check each one to see if it has the `.mydiv` class. Because IE *does* have a native `getElementsByTagName`, doing `div.mydiv` first fetches only the `div` elements, and checks only those for the class, so it is a bit faster for IE. If the `.mydiv` elements are all in one container, confining the search to that container will help too.
patrick dw