Skip to content

Instantly share code, notes, and snippets.

@talltyler talltyler/Main.as
Created Apr 28, 2011

Embed
What would you like to do?
ActionScript Spell Checking
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
public class Main extends Sprite
{
public function Main():void
{
var txt:TextField = new TextField();
txt.width = 550;
txt.height = 400;
txt.wordWrap = true;
txt.multiline = true;
txt.text = "One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The beding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pittifully thin compared with the size of the rest of him, waved about helplessly as he looked."
addChild(txt);
new SpellCheck(txt);
}
}
}
package
{
import com.adobe.linguistics.spelling.*;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextLineMetrics;
import flash.events.MouseEvent;
import flash.ui.ContextMenuItem;
import flash.events.ContextMenuEvent;
import flash.ui.ContextMenu;
/**
* SpellCheck, can be used with any TextField, based on this http://bit.ly/3cSZ2o
* You need the Squiggly swcs to compile this example!!
*
* @langversion ActionScript 3
* @playerversion Flash 9.0.0
*/
public class SpellCheck
{
private var _txt:TextField;
private var _canvas:Shape;
private var _checker:SpellChecker;
private var _bmpData:BitmapData;
private var _dict:HunspellDictionary;
private var _contextMenu:ContextMenu;
private var _begin:int;
private var _end:int;
public function SpellCheck(txt:TextField)
{
super();
_init(txt);
}
private function _init(txt:TextField):void
{
_txt = txt;
_bmpData = new BitmapData(2, 1, true, 0xFFFFFFFF);
_bmpData.setPixel32(0, 0, 0xFFFF0000);
_bmpData.setPixel32(1, 0, 0x00000000);
_dict = new HunspellDictionary();
if(_txt.parent == null) {
_txt.addEventListener(Event.ADDED_TO_STAGE, onTxtAddedToStage, false, 0, true);
}else{
_addCanvas();
}
loadDictionary();
}
private function loadDictionary():void
{
_dict.addEventListener(Event.COMPLETE, onDictLoaded);
_dict.load("en_US.aff", "en_US.dic");
}
private function _addCanvas():void
{
_canvas = new Shape();
_canvas.x = _txt.x;
_canvas.y = _txt.y;
_txt.parent.addChildAt(_canvas, _txt.parent.getChildIndex(_txt));
_txt.addEventListener(Event.CHANGE, onTextChanged, false, 0, true);
_txt.addEventListener(Event.SCROLL, onTextScroll, false, 0, true);
_contextMenu = new ContextMenu();
_contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, onTextClick);
_txt.contextMenu = _contextMenu;
if(_dict.loaded) {
_checkText();
}
}
private function onTextClick(event:ContextMenuEvent):void
{
_contextMenu.customItems = [];
var charIndex:int = _txt.getCharIndexAtPoint(_txt.mouseX, _txt.mouseY);
_begin = _txt.text.lastIndexOf(" ",charIndex)
_end = _txt.text.indexOf(" ",charIndex)
var word:String = _txt.text.substring(_begin,_end);
if(!_checker.checkWord(word)) {
var suggestions:Array = _checker.getSuggestions(word);
for each( var suggestion:String in suggestions ) {
var item:ContextMenuItem = new ContextMenuItem(suggestion);
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, onSelectContextMenuItem);
_contextMenu.customItems.push(item);
}
}
}
private function onSelectContextMenuItem(event:ContextMenuEvent):void
{
_txt.text = _txt.text.substring(0,_begin) + " " + event.target.caption + _txt.text.substring(_end,_txt.length);
_checkText();
}
private function _checkText():void
{
_canvas.graphics.clear();
// regex for matching next word...
var wordPattern:RegExp = /\b\w+\b/;
var inputValue:String = _txt.text;
var offset:int, curPos:int;
var found:Boolean = true;
var res:Array;
while(found) {
res = inputValue.match(wordPattern);
if(res == null) {
found = false;
}else{
curPos = inputValue.indexOf(res[0]);
if(!_checker.checkWord(res[0])) {
offset = _txt.text.length - inputValue.length;
drawErrorHighlight(offset + curPos, offset + curPos + (res[0].length-1));
}
inputValue = inputValue.substr(curPos + res[0].length);
}
}
}
public function drawErrorHighlight(beginIndex:int,endIndex:int):void
{
if(endIndex < beginIndex) return;
--beginIndex;
var rect1:Rectangle;
while(rect1 == null && beginIndex+1 < endIndex) {
rect1 = _txt.getCharBoundaries(++beginIndex);
}
// cannot find boundaries => letter is not displayed
if(rect1 == null) return;
++endIndex;
var rect2:Rectangle;
while(rect2 == null && endIndex-1 > beginIndex) {
rect2 = _txt.getCharBoundaries(--endIndex);
}
if(rect2 == null) return;
// if line isn't rendered, do highlight error
var lineNum:int = _txt.getLineIndexOfChar(beginIndex);
if(lineNum >= _txt.bottomScrollV) return;
// reposition canvas
var metrics:TextLineMetrics = _txt.getLineMetrics(lineNum);
var lineHeight:Number = metrics.ascent + metrics.descent + metrics.leading;
_canvas.y = _txt.y - (_txt.scrollV - 1) * lineHeight;
// get vals for drawing highlight
var x1:int = rect1.x;
var x2:int = rect2.x + rect2.width;
var y1:int = rect1.y + metrics.ascent + 2;
var w:Number = x2 - x1;
if(w > 0) {
_canvas.graphics.beginBitmapFill(_bmpData);
_canvas.graphics.drawRect(x1, y1, w, 1);
_canvas.graphics.endFill();
}
}
private function onDictLoaded(event:Event):void
{
_checker = new SpellChecker(_dict);
if(_canvas != null) _checkText();
}
private function onTxtAddedToStage(event:Event):void
{
_txt.removeEventListener(Event.ADDED_TO_STAGE, onTxtAddedToStage);
_addCanvas();
}
private function onTextScroll(event:Event):void
{
if(_dict.loaded) _checkText();
}
private function onTextChanged(event:Event):void
{
if(_dict.loaded) _checkText();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.