collect
drop
ContextJS Word Completion Demo
$world.withAllSubmorphsDo(function(m) { var p = m._Position if (p && p.x === undefined) p.x = 0; if (p && p.y === undefined) p.y = 0; })
Word Completion Example
■ While typing a word, the word is looked up in a dictionary If a word matches a preview is displayed If the user presses enter the word is replaced with the previewed word
1. Intercepting the Keyboard Events
Evaluate workspace by pressing CMD+S and see how the green example morph behaves during typing
cop.create('WordCompletionLayer').refineClass(lively.morphic.Text, { onKeyPress: function(evt) { var c = evt.getKeyChar(); alert('pressed "' + c +'"') cop.proceed(evt) } })
// create new morph m = new lively.morphic.Text(new Rectangle(0,0,100,30), "Hello") m.setPosition(pt(70,370)) this.owner.addMorph(m) // activate the layer for that morph m.setWithLayers([WordCompletionLayer])
Example TextMorph instance with instance specific activated WordCompletionLayer
Hello World
2. Finding the Last Word
cop.create('WordCompletionLayer').refineClass(lively.morphic.Text, { onKeyPress: function(evt) { var range = this.getSelectionRange() var cursor = range[0]; if (cursor > 0) { var lastWordRange = this.selectWord(this.textString, cursor - 1) var lastWord = this.textString.slice(lastWordRange[0], lastWordRange[1] + 1) alertOK("last word: " + lastWord) } return cop.proceed(evt) } })
Hello World
3. The Word Completion Logic
Object.subclass('WordCompletion', { completeAll: function(prefix) { if (this.wordList === undefined) return []; return this.wordList.select(function(ea) { return ea.startsWith(prefix) }); }, complete: function(prefix) { var lowerCasePrefix = prefix.toLowerCase(), list = this.completeAll(lowerCasePrefix).sort(function(a,b) { return a.length == b.length ? (a < b ? -1 : +1) : a.length - b.length; }); if (list.length === 0) return undefined; return lowerCasePrefix != prefix ? list[0].capitalize() : list[0]; }, loadWordList: function() { var dictUrl = 'http://lively-kernel.org/repository/webwerkstatt/marko/res/combinedWords.json', wordResource = new WebResource(dictUrl); this.wordList = JSON.unserialize(wordResource.get().content) } }); Object.extend(WordCompletion, { current: function() { // offline support var world = WorldMorph.current(); if (world.wordCompletion === undefined) world.wordCompletion = new WordCompletion(); return world.wordCompletion; } }); // WordCompletion.current().loadWordList() WordCompletion.current().wordList.length WordCompletion.current().complete("diff") WordCompletion.current().completeAll("diff")
4. Show preview in separate text morph
H
H
cop.create('WordCompletionLayer').refineClass(lively.morphic.Text, { showWordCompletionMorph: function() { if (this.wordCompletionMorph === undefined) { var m = new lively.morphic.Text(new Rectangle(), '').beLabel(); this.wordCompletionMorph = m; } this.wordCompletionMorph.applyStyle({textColor: Color.gray.darker(), fill: Color.white}); this.wordCompletionMorph.setFontSize(this.getFontSize()); this.addMorph(this.wordCompletionMorph); return this.wordCompletionMorph; }, hideWordCompletionMorph: function() { if (this.wordCompletionMorph) this.wordCompletionMorph.remove(); }, isShowingWordCompletionMorph: function() { return this.wordCompletionMorph && (this.wordCompletionMorph.owner === this); }, onKeyPress: function(evt) { var key = evt.getKeyChar(); if (!key.match(/\w/)) { this.hideWordCompletionMorph(); return; } var range = this.getSelectionRange() var cursor = range[0]; if (cursor > 0) { var lastWordRange = this.selectWord(this.textString, cursor - 1), lastWord = this.textString.slice(lastWordRange[0], lastWordRange[1] + 1) previewWord = WordCompletion.current().complete(lastWord); if (previewWord) { var m = this.showWordCompletionMorph(); m.setTextString(previewWord); m.setPosition(this.getCharBounds(lastWordRange[0]).bottomLeft()); } } return cop.proceed(evt) } });
5. Insert Previewed Word When Pressing Return
cop.create('WordCompletionLayer').refineClass(TextMorph, { onKeyDown: function(evt) { if (this.isShowingWordCompletionMorph() && evt.getKeyCode() == Event.KEY_RETURN) { var wordRange = this.locale.selectWord(this.textString, this.getCursorPos() - 1) var m = this.showWordCompletionMorph(); this.setSelectionRange(wordRange[0], wordRange[1] + 1); this.replaceSelectionWith(m.textString + " ") m.remove() return; // without proceed } return cop.proceed(evt) }, })
Hello World
6. Using new the new Feature
activate layer for all TextMorphs
WordCompletionLayer.beGlobal()
deactivate layer again
WordCompletionLayer.beNotGlobal()
PresentationContainer
X
M