Created
August 17, 2011 05:02
-
-
Save zhephree/1150840 to your computer and use it in GitHub Desktop.
AutoComplete in webOS Enyo
This file contains 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
/* | |
The CSS is pretty basic. The important part is to make sure your holder DIV has the exact same font family | |
and font size as your Input. We can't /actually/ calculate the width of a font, so we cheat. We do this by | |
copying whatever text is in the Input into a hidden DIV. That Div is set to expand its width as the content | |
changes. We can then guess about how wide the block of text is. I set a max-width on the DIV so that it won't | |
push the suggestions list too far off the screen, even though we account for that in the keypress function. | |
*/ | |
.holder { | |
position: absolute; | |
left: 0; | |
top: 0; | |
visibility: hidden; | |
pointer-events: none; | |
font-size: .9rem; | |
width: auto; | |
max-width: 570px; | |
height: auto; | |
} |
This file contains 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
/************************ | |
Autocomplete in Enyo. This is a guide, not a copy-pasta chunk of code. It's to illustrate how I did it. Teach | |
a man to fish, etc., etc. If you use this, that's cool. Just give me a shout out somewhere. Twitter, blog, | |
release notes, source code, whatever. | |
I doubt this is the best way, and it's definitely not the only way, but I figure there's some pointers that | |
could lead you to something cool. | |
************************/ | |
/* | |
Add a plain old HtmlContent component to your app. It'll be hidden. We'll handle the CSS in the other file | |
*/ | |
{name: "holder", kind:"HtmlContent",className:"holder"} | |
/* | |
Make sure you listen to the keypress event for your Input box. I'm watching for the @symbol for Twitter | |
accounts, but you could check against a space to start a new word. | |
You'll want a Popup component with a VirtualRepeater in it to display your results. Mine's named "autoCompleteBox" | |
and its VirtualRepeat is "autoCompleteList" | |
"publisherInput" is my Input, obviously. | |
*/ | |
publisherInputKeyPress: function(inSender,event,value,d){ | |
//handle autocomplete | |
var cursor=inSender.getSelection(); | |
var leftChar=value.charAt(cursor.start); //get the character to the left of the cursor | |
if(leftChar=="@"){ | |
//console.log("we're atin'"); | |
this.atStart=cursor.start+1; | |
this.autoComplete=true; | |
}else{ | |
if(leftChar==" " || value.indexOf("@")==-1){ | |
//if we're starting a new word or the @ was removed, close the box | |
//console.log("hit a space"); | |
this.atStart==-1; | |
this.autoComplete=false; | |
this.$.autoCompleteBox.close(); | |
} | |
if(this.autoComplete){ | |
//figure out the chunk of text to use as a search | |
var space=value.indexOf(" ",this.atStart); | |
if(space>this.atStart){ | |
var end=space-this.atStart; | |
var searchString=value.substr(this.atStart,end); | |
}else{ | |
var searchString=value.substr(this.atStart); | |
} | |
//console.log("search="+searchString); | |
var searchArray=[..]; //this would be the array of things to search. could be a DB even | |
//console.log(friends); | |
this.suggestions=[]; | |
for(var f=0;f<searchArray.length;f++){ | |
if(this.suggestions.length==5){ | |
break; | |
} | |
if(searchArray.username.indexOf(searchString)>-1){ //change ">-1" to "==0" for startsWith search | |
this.suggestions.push(searchArray[f]); | |
} | |
} | |
if(this.suggestions.length>0){ | |
//re-render the VirtualRepeater. You can figure this out | |
this.$.autoCompleteList.render(); | |
//set the content of our hidden DIV to the same as our Input to measure the text width | |
this.$.holder.setContent(value); | |
//get the width of our hidden DIV | |
var textWidth=this.$.holder.getBounds().width; | |
//get the positions of our popup and the autocomplete suggestions popup | |
var pl=this.$.publisherPopup.getBounds(); | |
var bl=this.$.autoCompleteBox.getBounds(); | |
//calculate the left of the suggestions. fudge it a bit so it won't cover the cursor | |
var left=textWidth+pl.left+40; | |
var top=50; | |
//make sure the suggestions list stays on the screen | |
if((left+bl.width)>screen.width){ | |
left=screen.width-bl.width-7; | |
top=100; | |
} | |
//open our suggestions list popup at the precise left | |
this.$.autoCompleteBox.openAtControl(inSender,{top: top,left: left}); | |
//however, if the box is already open, we have to manually set its left | |
//this moves the box to the right a bit as we type | |
this.$.autoCompleteBox.applyStyle("left",left+"px"); | |
}else{ | |
//bail if autocomplete is unnecessary | |
this.$.autoCompleteBox.close(); | |
} | |
} | |
} | |
}, | |
//handle when an autocomplete item is tapped | |
suggestionSelect: function(inSender,inEvent){ | |
var sug=inEvent.rowIndex; | |
var row=this.suggestions[sug]; | |
//find the cursor position, the value of the Input, and the chunk of text we used for searching | |
var cursor=this.$.publisherInput.getSelection(); | |
var value=this.$.publisherInput.getValue(); | |
var partial=value.substring(this.atStart-1,cursor.start); | |
//quick and dirtily replace the @ and the chunk with the full item | |
this.$.publisherInput.setValue(value.replace(partial,"@"+row.username+" ")); | |
//move the cursor to the end of the Input | |
var len=this.$.publisherInput.getValue().length; | |
this.$.publisherInput.setSelection({start:len,end:len}); | |
//turn off autocomplete and close the list of suggestions | |
this.autoComplete=false; | |
this.$.autoCompleteBox.close(); | |
}, | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Whoa! That's awesome!