2

I am dealing with HTML that's been generated with FCKeditor. So it will look something like this:

<p>Paragraph</p>
<ul>
<li>List item</li>
</ul>

No head tag, no body tag, just a snippet of HTML.

I am trying to add support for certain variables that, when inserted into the HTML, will be replaced with dynamic content. So the HTML, variable inserted, might look like this:

<p>Here's a variable: {widget}</p>

I want to replace {widget} with this:

<div class="widget">Hi, I'm a widget.</div>

FCKeditor encapsulates content (rightly) into paragraphs when you insert a line break. So if I did a straight replace, the resulting HTML would be this:

<p>Here's a variable: <div class="widget">Hi, I'm a widget.</div></p>

That's not going to work because the div tag is inside of the p tag. So what I want to do is close the paragraph and insert the DIV after it:

<p>Here's a variable: </p>
<div class="widget">Hi, I'm a widget.</div>

Let's take this example:

<p class="someclass">Here's a <strong>variable: {widget} more</strong> content 
after</p>

I would want this result:

<p class="someclass">Here's a <strong>variable: </strong></p>
<div class="widget">Hi, I'm a widget.</div>
<p class="someclass"><strong> more</strong> content after</p>

At every instance of {widget} in HTML snippet, I need to make a "break" in the HTML. Which is to close every open tag, insert the widget code, then open them all again in order.

Is this possible using a PHP HTML parser? If so, how would I go about it?

mattalxndr
  • 9,143
  • 8
  • 56
  • 87
  • This is a good question, I curious to see the answers. Sorry I can't offer any assistance! – Sean Walsh Feb 16 '11 at 19:05
  • 1
    Wow, that's a tough one. DOM won't, [regex won't](http://stackoverflow.com/questions/1732454), ... – Jonah Feb 16 '11 at 19:06
  • 1
    any reason why you are using div for your widget content, you will save yourself lots of grief if you use inline element like span for example – Kris Ivanov Feb 16 '11 at 19:09
  • @K Ivanov The widget thing is just an example. There will be many different types of widgets. Virtually all of them will contain block-level elements. – mattalxndr Feb 16 '11 at 19:11
  • @Jonah Thanks for reminding me about that [funny regex link](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454), but I would never look to regex to solve a problem like this. – mattalxndr Feb 16 '11 at 19:13

2 Answers2

1

I would suggest an entirely different approach. (F)CKEditor can already do what you want. Just try to add a table in the middle of a paragraph. It will close the inline tag stack, add the table, and reopen the stack again.

I suggest that, instead of having your users write {widget}, you write an (F)CKEditor plugin that adds the widgets for you. You can take a look at the code for the table button (or any other block-level element) to see how (F)CKEditor inserts them.

There are two things you can do when a user hits the "widget" button. Eitther you insert some custom tag such as <widget type="foo" />, or you insert a HTML tag that you can recognise later on, like <div class="widget foo"></div>.

With some extra elbow grease you can even make this fancier by actually loading the widget itself, wrapped in such tags. That way, the user would see exactly the same in the editor window as when it was stored. When the editor saves to the server, simply empty the tags wrapping the widget to get rid of it.

Example workflow (cursor marked by | sign):

User types text:

<p>foo bar| baz</p>

User hits "widget" button:

<p>foo bar</p>
<div class="widget foo"> ... contents of "foo" widget ... </div>
<p>|baz</p>

When saving, drop the widget contents:

<p>foo bar</p>
<div class="widget foo"></div>
<p>baz</p>

When displaying the saved contents, parse for div tags with a "widget" class and dynamically fill it:

<p>foo bar</p>
<div class="widget foo"> ... contents of "foo" widget ... </div>
<p>baz</p>
Sander Marechal
  • 22,978
  • 13
  • 65
  • 96
  • Actually, the way FCKeditor is handling my custom DIV is a little weird, but that's a question for another question. – mattalxndr Feb 18 '11 at 16:30
0

This could be done post-process when saving with regex if you were pretty careful about what you allowed. Alternatively, I do a fair amount of juggling on the front end with my editor (CKEditor) output, combining the user-input content plus things that I jam in both between and around the string that I parse and regex.

Another option to be explored is the BBCode plugin that CKEditor has added. Having been a longtime user of FCK plus a current user of CK, I can tell you that it's well worth the time to make the upgrade. And, according to the CK Developer site, it claims to be built-in. I also found a plugin that will allow BBCode. Both could easily be adapted for your purpose.

Finally, if you're adventurous and confident with Javascript, the HTML Processor can be hacked to do quite a few things. For instance, CK now outputs with styles rather than traditional HTML, and my editor does strictly HTML Emails which don't support style declarations so well. So, I hacked the HTML Processor's code to output everything with height=, width=, align= etc rather than style="height=x; width=x" etc.

bpeterson76
  • 12,918
  • 5
  • 49
  • 82