i want to add live searching to a list whose data provider is a very large XML. for simplicity, let's assume my XML is just a list of the world's 180ish countries:
package
{
//Imports
import fl.controls.List;
import fl.data.DataProvider;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
//Class
public class LiveSearchXMLList extends Sprite
{
//Variables
private var XMLData:XML;
private var dp:DataProvider;
private var list:List;
//Constructor
public function LiveSearchXMLList()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
//Initialization
private function init(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//Download XML File
var XMLLoader:URLLoader = new URLLoader();
XMLLoader.addEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
XMLLoader.addEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);
XMLLoader.load(new URLRequest( /* COUNTRY_LIST_XML_FILE */ ));
}
//XMLLoader Error Handler
private function IOEventErrorHandler(evt:IOErrorEvent):void
{
//Remove Event Listeners
evt.target.removeEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
evt.target.removeEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);
//Throw Error
throw(evt.text);
}
//XMLLoader Complete Handler
private function XMLLoaderCompleteEventHandler(evt:Event):void
{
//Remove Event Listeners
evt.target.removeEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
evt.target.removeEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);
//Assign XMLData
XMLData = new XML(evt.target.data);
createList();
}
//List
private function createList():void
{
//Assign And Alphabetize Data
dp = new DataProvider(XMLData);
dp.sortOn("countryName");
//Create List Object
list = new List();
list.width = 400;
list.height = 400;
list.x = list.y = 25;
list.labelField = "countryName";
list.dataProvider = dp;
}
}
}
the list's labelFields are populated by the XML element's <countryName>
and alphabetized.
i would like to create an input text fie开发者_开发技巧ld that will listen for keystrokes and update the list according to the input string matching the countryName element values. therefore, if i enter "can" in the text field, the list will suddenly be reduced to only 5 rows:
- American Samoa
- Canada
- Central African Republic
- Dominican Republic
- Vatican City
of course, live search should be non destructive as well - press delete once so the search field now reads "ca", which increases the 5 row list to 21 rows. (Antarctica, Jamaica, etc.)
how is this done? what is the fastest or most common approach for live searching and updating an XML provided list object?
Personally, unless you have a reason to keep your data as xml, I would transform the xml list into an arrayCollection of objects first. If you do that when you load the data it should give you some better performance overall, especially with larger data sets.
But to answer your question, I would do something like this: (this assumes you transform the xml data into an arrayCollection called _acData and you have another arrayCollection called _acFilteredData that is what the list control is bound to. Once you load up the data into _acData, copy it into _acFilteredData and then attach a function like this to your text input)
private function inpFilter_change ( e:Event ) : void
{
var searchString:String = StringUtil.trim(inpFilter.text).toLowerCase();
if ( searchString.length )
{
var newAC:ArrayCollection = new ArrayCollection();
for each ( var tempObject:Object in _acData)
{
if ( tempObject.countryName.toString().indexOf(searchString) != -1 )
{
newAC.addItem(tempObject);
}
}
_acFilteredData = newAC;
listControl.dispatchEvent(new ListEvent(ListEvent.CHANGE)); //might not be necessary, but will force the control to update
}
else
{
_acFilteredData = _acData;
}
}
精彩评论