Forum OpenACS Q&A: Instructions on how to make your package support HTMLArea

How to enable WYSIWYG for ad_form

Since I beliew that a WYSIWYG-Editor is essential for the future of OpenACS I sifted through various postings and irc-blogs to create a simple How-To for moving HTMLArea to your package forms

Step 1 (optional): Converted your page to use ad_form (lots of changes but worth it)

Here an examples. From:
template::form create my_form
template::element create my_form my_form_id -label "The ID" -datatype integer -widget hidden
template::element create my_form my_input_field_1 -html { size 30 } -label "Label 1" -datatype text -optional
template::element create my_form my_input_field_2 -label "Label 2" -datatype text -help_text "Some Help" -after_html {Anchor}
To:
ad_form -name my_form -form {
	my_form_id:key(acs_object_id_seq)
 	{my_input_field_1:text,optional
               {label "Label 1"}
               {html {size 30}}}
      	{my_input_field_2:text
               {label "Label 2"}
               {help_text "Some Help"}
	       {after_html
               {Anchor}}}
}

Step 2: Convert your textarea widget to a richtext widget and enable htmlarea.

The htmlarea_p-flag can be used to prevent WYSIWYG functionality. Defaults to true if left away.
From:
{my_input_field_2:text
To:
{my_input_field_2:richtext(richtext)
		{htmlarea_p "t"}

Step 3: Working with richtext correctly


The richtext widget presents a list with two elements (text and content type). For a list of existing content types (mime-types/a>) see here or in the cr_mime_types table. You have to make sure that both a list is passed to ad_form when displaying the content and likewise to handle data manipulation correct. Now depending on your data model you either support a content format or don't. If you don't you can assume "text/html" or "text/richtext" or "text/enhanced" (in the following we will use "text/html"). The relevant parts in ad_form that are effect are the switches -new_data, -edit_data, -on_request and -on_submit. We will go through them now.
  1. To allow your data to display correctly you need to add an -on_request block. Here enter the following. If you have the format stored in the database pass this as well else use "text/html":
    set my_input_field_2 [template::util::richtext::create $my_input_field_2 "text/html"]
    
  2. Now you have to make sure that your SQL queries that do the data manipulation retrieve the correct value. If you simply use my_input_field_2 you will store a list. Thus you need to add an -on_submit block:
    set my_input_field_2 [ template::util::richtext::get_property contents $my_input_field_2]
    set format [ template::util::richtext::get_property format $my_input_field_2] #This is optional
    
  3. Now you can forward the correct value to your -new_data amd -edit_data blocks. They only differ in their behaviour. But each will use the adjusted variables my_input_field_2 and format withing their corresponding DML queries to set the values correctly.

Making HTMLArea optional per package intance

  1. Goto your package under APM and define the number parameter "UseWysiwygP" with default 0
  2. Change your edit page as follows
    # Is WYSIWYG enabled?
    set use_wysiwyg_p [parameter::get -parameter "UseWysiwygP" -default "f"]
    
    ...
    
    {htmlarea_p $use_wysiwyg_p}
    
  3. And pass set the value on_request time
    set htmlarea_p $use_wysiwyg_p
    
  4. Now create a configuration page where the user can change the settings
    TCL:
    ad_page_contract {
    
        configure.tcl
        This page allows a faq admin to change the UseWysiwygP setting.
    
        @author Nima Mazloumi (nima.mazloumi@gmx.de)
        @creation-date  2004-08-11
    
    } {
        {return_url ""}
    }
    
    set title "Should we support WYSIWYG?"
    set context [list $title]
    
    set use_wysiwyg_p
    
    ad_form -name categories_mode -form {
        {enabled_p:text(radio)
            {label "Enable WYSIWYG"}
            {options {{Yes t} {No f}}}
            {value $use_wysiwyg_p}
        }
        {return_url:text(hidden) {value $return_url}}
        {submit:text(submit) {label "Change"}}
    } -on_submit {
        parameter::set_value  -parameter "UseWysiwygP" -value $enabled_p
        if {![empty_string_p $return_url]} {
            ns_returnredirect $return_url
        }
    }
    
    ADP:
    <master>
    <property name="title">@title@</property>
    <property name="context">@context@</property>
    
    <formtemplate id="categories_mode"></formtemplate>
    
  5. And make a link in your admin page
    TCL:
    set return_url [ad_conn url]
    
    ADP:
    <a href=configure?<%=[export_url_vars return_url]%>>Configure</a>
    

Thanks

To all who contributed parts and hints - see below.

References

Nima: this is great! Any chance you'd be willing to add this to the documentation, under the tutorial section? It's not terribly difficult (see https://openacs.org/faq/one-faq?faq_id=161579)
Added to documentation on HEAD. Hope I didn't do any harm ;)
Strange but true. The form name MUST be different to the name of your page. Otherwise HTMLArea won't load.
Great documentation!

I have a question dough, we recently updated our code and now we have the nice richtext widget, but the problem is that in our database we have content with the "text/html" and content without it. Besides, I need to display his content inside a portlet (I have this problem whit the static portlets, but I also want to dislay the contents in other pages --"outside" an ad_form--). Right now the content is shown like "{<ul>blah blah..} {text/html}", but the content of some other portlets is shown like "content", how can I differentiate between theese cases?, is there a proc that handles this case?, and what about the interpretation of the html tags? shall I do it with @varname;noquote@ in the adp files or is there another way?

Thanks!, regards, Jose

Jose,

I guess if this happened because you switched to HTMLArea you should write a little SQL query that replaces old entries "xyz" with {xyz} {content-type}. The problem is that you don't  know necessarily the content type of that content, right?

Maybe [ad_looks_like_html_p $content] would help. Or you use [util_remove_html_tags $content] and if the result is smaller than what came from database then it is HTML.

You can also leave the content as it is in the database and use the following to distinguish. This is what I do for static-portlet:

set success_p [db_0or1row select_content {
  select body as content, pretty_name
  from static_portal_content
  where content_id = :content_id
}]

set size [llength $content]
if { $size == 2} {
    set content [lindex $content [expr [llength $content]-2]]
}

So if it is a list with two elements I assume that it is richtext and I only take the first element with the actual content.

In the ADP I then simply use:

@content;noquote@

Regarding the interpretation of HTML we have several procs to handle that:

ad_convert_to_html text
ad_html_to_text html
ad_text_to_html text
util_convert_line_breaks_to_html text
util_remove_html_tags html
ad_html_security_check html
...

Greetings,
Nima

Collapse
Posted by Ben Koot on
Hi folks,

Are there any objections to have the WYSIWYG function available as default, with a "simple" paramater function to turn it off. (instead of today's option to activate it,and having to go through this customisation under the hood)) it seems to me, from a userability standpoint, I can't expect many people to have a problem with that.

As a matter of fact, my latest client regards this as a pre-requisite, so it's to bad we have to manipulate the system to such an extend.

The curent parameter function seems to suck, as it frustates overall default editing functionality.

Thanks

Ben

I totally agree. Maybe we can add a link for an site wide administrator to the HTMLarea enabled widget for turning it off (for all / for this package).
There's a acs-templating parameter, UseHtmlAreaForRichtextP, which controls whether richtext widgets use the htmlArea.
Is this what you mean?
Rocael is right. The other this concerns more to the APM in general. We need to be able to define instance and package wide parameters.
I know about the acs-templating parameter, but I would appreciate if I had the option to turn on/off HTMLarea like I can turn on/off the .LRN status bar (using a link), along with the possibility to to this package instance dependend (which introduces the need for storing package instance parameters that are defined site-wide and added to each package instance)
Hello,

Is there a way to use the richtext with the original template::form ?

I've tried changing mine to use ad_form but it just spits up a bunch of errors (my syntax is probably wrong, but I'm taking on a project that's already been implemented, and feign to change to use a new form environment).

Any help would be great, thanks.

Jon

Jon, yes, it is possible, I believe. I don't know enough to help you out further, however!
Further to my default question. Once you activate the WYSIWYG editor, the default OACS formatting functions are screwed up. Some how that set up doesn't make sense.

Question is why would anyone settle for less functionality than offered by the the WYSIWYG editor if it's allready in the toolkit? Why not disable the minimal default functions alltogether, and make the editor default. It looks like the dual option messes up the system. Afterall, the editor's functions are optional anyway.

It may be an effort to clean up the code, but it would eliminate a lot of discusion, especially since new users will be wondering why we havn't closed this issue.

1. I have a feeling end users will love to have the functionality.

2.It helps consultants to sell an oacs solution if they don't have to explain that WYSIWYG is an added bonus. That sort of speak doesn't make sense anymore in 2005.

If I am missing a point and/or oversimplify things, sorry for that. In that case maybe we could set it as a future milestone.

cheers

Ben