views:

145

answers:

2

Ok I give up and would really appreciate it if you guys could cast their eye over this for me? I'll try not to ramble.

Goal is to have a 'rendered-view' showing 'rendered' HTML (clickable links) and 'source-view' showing the actual HTML of whatever is in the rendered view. When a link is clicked it is made not a link any more and simply becomes the anchor text. The source then needs to update to reflect this. That's the idea anyway.

The rendered links have an id, href, title and class attributes plus a <strong> tag. I don't want the id, title or class to show in the source view.

I have it so upon clicking, the 'href' and <strong> are removed, then I remove the class and title from ALL links. I need to keep the id in source view so the undo function I've created still works.

So, the problem is basically:

<div> with id of 'rendered-view' contains the rendered version of:

<a id="link1">blah blah</a>
<a id="link2" href="http://www.somesite.com"&gt;&lt;strong&gt;Visit this site</strong></a>

i.e:

blah blah

Visit this site

Source view should result in:

blah blah
<a href="http://www.somesite.com"&gt;&lt;strong&gt;Visit this site</strong></a>

I know a regular expression will be needed which is where I fail badly at the moment. I'm a PHP guy really and brand new to jQuery so would appreciate the help.

A: 

See the question/answer: You can't parse [X]HTML with regex. Because HTML can't be parsed by regex. Regex is not a tool that can be used to correctly parse HTML...

But seriously, what you want to do can probably be done much better with JavaScript and DOM manipulation. I know a lot more about Prototype than jQuery, and I could code this in Prototype fairly easily, but I would highly recommend using the HTML parser built-in to the browser. My basic approach would be something like:

  1. Insert the encoded HTML into both the source-view and the rendered-view
  2. Loop through all elements of the source-view:
    1. If the element is a link, remove the id, title and class
  3. Encode all HTML entities in the source-view innerHTML; prototype does do this with a regex: String.prototype.escapeHTML = function() { return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }
  4. Loop through all child a elements of the rendered view
    1. Observe their click event and attach your custom handler, canceling the default handler
    2. Perform any other processing to these you might need to. (I'm still a bit foggy on what it is you're trying to accomplish)

I know I'm providing a bit of a vague answer to your question... if I were better with jQuery I could provide some actual code, which I'm sure is what you want. Any jQuery experts want to help Jon out? :-)

Josh
Why everyone quotes THAT discussion every time someone mentions HTML and regex in same sentence? This one is **not** about parsing! It is about replacing chars that would generate HTML rendition with their escaped counterparts; perfect for regexp. Am I missing something?
Marko Dumic
You may be missing that he wants to remove HTML attributes, CSS classes, IDs, etc. It seems like he really should be walking the DOM tree. Note I did suggest using a regex to encode HTML entities.
Josh
Thanks, I missed that. I've updated my answer.
Marko Dumic
Nice work. Now, you too are using a DOM parsing engine :-)
Josh
+3  A: 

Suppose you have two divs with id's rendered and source:

Rendered:
<div id="rendered" style="border: 1px solid #000">
    <a id="link1">blah blah</a>
    <a id="link2" href="http://www.somesite.com"&gt;&lt;strong&gt;Visit this site</strong></a>
</div>
Source:
<div id="source" style="border: 1px solid #000">
</div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

Then this populates the other div with the source of first div, removing some of the attributes (id, title and class):

$('#source').html(
    $('#rendered')
        .clone()
        .find('*')
            .removeAttr('id')
            .removeAttr('title')
            .removeAttr('class')
        .end()
        .html()
        .replace(/\&/g, '&amp;')
        .replace(/\</g, '&lt;')
        .replace(/\>/g, '&gt;')
);​

Of course, you need to run this after the DOM is ready.

(I'm not sure about the necessity of &amp escaping.);

Marko Dumic
The test suite: http://jsfiddle.net/eWFGU/
Marko Dumic
Jon
@Jon: You should accept Marko's answer by clicking the check mark next to it, this will show others that the question has been answered (and give him +15 rep)
Josh