Name

CGI::Form::Spell — this is alpha software.

Version

0.10

Abstract

Spell checking with perl is easy. Web forms with perl are easy. Spell checking in web forms is a hassle. This module provides fully automated spell checking with just two method calls and hooks to customize the checks on user entered form fields.

Synopsis

 use CGI qw(:standard);
 use CGI::Form::Spell;

 my $spell = CGI::Form::Spell->new();

 print
    header(),
    start_html(-title => 'Speling iz phun',
               -head  => style({type => 'text/css'},
                               $spell->default_styles(),
                               ),
               ),
    start_form(),
    textarea(-name => 'myField',
             -default => "This is speled qite porly."),
    submit('go!'),
    end_form(),
    $spell->correction_block('myField'); # run check and do output

Description

CGI::Form::Spell provides a drop-in way to use the excellent GNU Aspell library, via Text::Aspell , to check and dynamically correct, via JavaScript, spelling in user entered form fields.

This module falls between a toolset and a plug-in application. While easy to use, utilitarian, and somewhat cutomizable, it is also locked into several assumptions.

DHTML — it must have JavaScript support in the client browser and user defined CSS support is recommended.

It can only be applied to user editable web form fields; specifically, text type inputs and textarea fields.

It must have Text::Aspell installed with the dictionary file(s) available to the webuser.

Some optional external/online resources, online dictionaries, are hardcoded and could change at any time.

Rationale

I use and adore this kind of code in every single web application I write and I’m A) sick of rewriting it slightly differently over and over, and B) sure that others will find it useful.

A note about "words"

Asdf asdf asdf.

Methods

my $spell = CGI::Form::Spell->new
Creates a new spelling object. No creation arguments are accepted right now.
$spell->spellcheck(‘field_name’)
Returns a list of misspelled "words" in the form field whose name is passed.
$spell->aspell
Gets the underlying Text::Aspell object.
$spell->correction_block(‘form_field_name’)
Returns a set of HTML which has each incorrectly spelled "word" highlighted and linked to an outside resource (the "web_dictionary"). The word is followed by a list "max_suggestion" count or shorter long of spelling suggestions that Aspell returns.
See the CSS class diagram below for an outline of the correction block and its HTML.
$spell->suggest(‘rongish’)
Takes an incorrect word and returns the max_suggestion count of possible corrections as JavaScript links. If you want to get a plaintext list of corrections you can always ask the aspell object directly. Eg:
 $spell->aspell->suggest('rongish')
$spell->max_suggestion
Set and get the maximum suggestions Aspell will return for misspelled words. Default is "8." In my experience Aspell either gets it right in the first 7 or number 20 or so or not at all. Shorter lists are less of an eyesore.
$spell->web_dictionary( $preset_key || $user_url )
Set or get the web dictionary that terms will be linked to to lookup if the user wants to click through.
Takes a key for one of the preset dictionaries or a full URL to a dictionary’s search form (see "Online dictionaries" below).
$spell->dictionary_link(‘term_to_lookup’)
Returns a URI escaped link to whatever web_dictionary has been set. So if you give it, "george orwell," and the dictionary is set to "answers," the URI you get back will be: http://www.answers.com/george%20orwell
$spell->suggest_separator and $spell->term_separator
See the CSS diagram for more.
$spell->form_name
Sets the form name for the spell checks. The JavaScript can normally auto-discover this correctly but if your form is named, you may need to set it if other forms on the same page reuse field names. Eg, you have one form named "search" which has a field named "query" and another form named "quote" which also has a field named "query."
$spell->default_styles
A convenience to spit out a reasonable set of CSS. See the "Synopsis" for a simple way to use it with CGI.
$spell->correction_javascript
$spell->321

Private methods

You know the drill. Don’t use these. Or do. I’m not your mother.

$spell->_correct_link
Used to write out the JavaScript link which will do a find/replace on the form field using the JavaScript from correction_javascript.
$spell->_bad
Gets the array or array ref of incorrect terms from the last spellcheck.
$spell->_current_name
Whatever the last spellchecked field name is
$spell->_javascript
Gets the <script> which handles the find and replace in form fields.

Appearance and CSS classes

If you want to customize the output of the "correction_block," you should do so with CSS classes in your HTML.

The classes in correction_block‘s output

CSS outline/diagram

This is an outline of the output of the method correction_block.

 ___correctBlock_(div)________________________________________
 | __correctLine_(div)______________________________________ |
 | | speltWrong (a) -- correctLink (a) * correctLink (a)...| |
 | |_______________________________________________________| |
 | __correctLine_(div)______________________________________ |
 | | speltWrong (a) -- correctLink (a) * correctLink (a)...| |
 | |_______________________________________________________| |
 | ...                                                       |
 |___________________________________________________________|

Related methods

I really wish those could be left out in favor of ":before" and ":after" CSS but it’s in CSS2 and that’s not everywhere yet. If you want to do this in your own set-up and CSS, you can set the separators to an empty string.

 $spell->suggest_separator('');
 $spell->term_separator('');

Online dictionaries

There are several presets. The default right now is ‘answers’ because they don’t do popups and their site provides definitions hand-in-hand with encyclopedia entries; "misspellings" are often proper nouns that didn’t make it into standard dictionary files.

 # Answers.com, the default
 $spell->web_dictionary('answers');

 # Wiktionary
 $spell->web_dictionary('wiktionary');

 # TheFreeDictionary.com
 $spell->web_dictionary('free');

 # hyperdictionary
 $spell->web_dictionary('hyper');

 # Google
 $spell->web_dictionary('google');

 # Merriam-Webster
 $spell->web_dictionary('mw');

 # Free Oxford English
 $spell->web_dictionary('oed');

 # Bartleby.com's dictionaries
 $spell->web_dictionary('bartleby');

I have no business relationship with, and do not specifically endorse, any of them. I’ve included most of the prominent ones and if I’ve missed one you would rather have, go ahead and set it yourself. Nota bene: both of the following contain mature material.

 # Hey, who am I to judge?
 $spell->web_dictionary('http://www.urbandictionary.com/define.php?term=');

 # Now that's a dictionary!
 $spell->web_dictionary('http://sedition.com/ddx/x/s.cgi?_q=');

Note, you must provide a URI which beghin with "http://\w" and can be direct affixed with the uri_escaped term to search.

Text::Aspell

The Text::Aspell object is available through the CGI::Form::Spell object in its aspell method. Any of Text::Aspell ‘s methods can be invoked on the object it returns. For example, to see the installed dictionaries:

 print $spell->aspell->list_dictionaries();

Or to set a custom user dictionary file and then manually add a word to it:

 $spell->apsell->set_option('home-dir', '/some-writeable-dir');
 if ( $spell->aspell->add_to_personal($term) ) {
     print h3("success!");
     $spell->aspell->save_all_word_lists();
 }

See your built-in documentation for aspell and the perldoc for Text::Aspell for more information and options.

To do

Give user a chance to add an "add to dictionary" link and its text. Put a JS alert on it with maybe a no_alert() switch if the user really doesn’t want it. Or as part of the config for it.

Allow user defined word regex and improve default. Or organize some options under keys so numbers can be excluded, punctuation changed, etc.

Allow for global find/replace as opposed to the each it’s doing now. And make the inline ones do the one they represent, not the first one. Also should put an ignore tag (?) to collapse that correction line and maybe save it in the session?

Consider adding JS cookies to support per session/user spelling exceptions with an "ignore" onclick link.

Notes for how to custom install it locally without root.

Weigh whether or not to do a real HTML strip instead of the naive one it’s using now so alt and such can be checked as well.

TT2 sample.

Add support for Text::Ispell so user can use it instead of Text::Aspell …?

Bugs

Could be. I’ve only tested the JavaScript on a handful of browsers for Macintosh so I’m not positive it’s rock solid.

I appreciate any bug reports or other contructive feedback.

Alternatives

This structure is a bit rigid. There is no reason you can’t do the same sorts of things to your own taste with the underlying tools if you’re capable. Feel free to bite or adapt the JavaScript from this module.

Author

Ashley Pond V (ashley@cpan.org).

Copyright and Credits

Copyright 2005, Ashley Pond V. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

This would be impossible without the excellent work of Kevin Atkinson (Aspell) and Bill Moseley (Text::Aspell).

I also recommend O’Reilly’s Monkey Book, "JavaScript & DHTML Cookbook." It’s truly useful for web development. My affiliate link to the book on Amazon if you’re feeling frisky: http://www.amazon.com/exec/obidos/ASIN/0596004672/elektrum-20 or not: http://isbn.nu/0596004672

How to get the module

It’s not on the CPAN and I’m not sure when/if it will be. It strikes me as more application than tool. But I may be able to generalize it enough that I think it should go up.

It should be available at: http://sedition.com/perl/aux/CGI-Form-Spell-0.10.tar.gz