Created
April 28, 2011 14:58
-
-
Save talltyler/946504 to your computer and use it in GitHub Desktop.
ActionScript Spell Checking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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