分享

自己写的模拟combobox的flex4实现,带分页,支持键盘操作

 firefly87 2012-04-23
自己写的模拟combobox的flex4实现,带分页,支持键盘操作
2010-12-06 21:45
前段时间本来想用combobox,但是总是在textinput中输入的时候出现问题,和网上的朋友交流说是是一个bug,看了一下原码,限于本人的水平问题,重写比较困难,所以放弃了。于是自己写一个组件,基本上效果还算满意。先贴个图:


实现代码:前台用json数据作为数据源,需要另下支持json的flex压缩包,放到flex项目的lib下即可。


<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300" creationComplete="init()">
    <s:layout>
        <s:BasicLayout/>
    </s:layout>
    <fx:Declarations>
        <s:HTTPService id="httpService" result="success()" fault="failure()" resultFormat="text" method="POST" useProxy="false" showBusyCursor="true"/>
        <s:HTTPService id="recordsService" result="recordsResult()" fault="failure()" resultFormat="text" method="POST" useProxy="false" showBusyCursor="true"/>
    </fx:Declarations>
    
    <fx:Script>
        <![CDATA[
            import com.adobe.serialization.json.JSONDecoder;
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.events.ListEvent;
            import mx.managers.CursorManager;
            import mx.managers.FocusManager;
            
            import spark.events.IndexChangeEvent;
            import spark.events.TextOperationEvent;
            //计时器
            private var timer:Timer;
            
            [Bindable]
            private var datas:ArrayCollection = new ArrayCollection();
            private var label:String;
            private var same:Boolean = false;
            //可以直接传sql给此组件
            private var _sql:String = "";
            //页号
            [Bindable]
            private var start:int = 1;
            //第页记录数
            private var limit:int = 10;
            //总页数
            [Bindable]
            private var totalPage:int = 0;
            //总记录数
            [Bindable]
            private var records:int = 0;
            //初始化方法
            private function init():void {
                //textinput的宽度,在这里设置一次,list和最下方的按钮栏则会同时改变
                input.width = 150;
                list.width = input.width;
                list.x = input.x ;
                list.height = 150;
                list.depth = 100;
                bbar.width = input.width;
                bbar.visible = false;
                list.visible = false;
                //设置计算器为1秒后发送请求,只发一次
                timer = new Timer(1000,1);
                input.addEventListener(FocusEvent.FOCUS_IN,focusIn);
                input.addEventListener(TextOperationEvent.CHANGE,onChange);
                timer.addEventListener(TimerEvent.TIMER_COMPLETE,timerFinished);
                list.addEventListener(IndexChangeEvent.CHANGE,clickItem);
                addEventListener(MouseEvent.CLICK,outClick);
                list.addEventListener(MouseEvent.CLICK,clickList);
                list.addEventListener(FocusEvent.FOCUS_OUT,focusOut);
                input.addEventListener(KeyboardEvent.KEY_UP,up);
                
                //以下是设置按钮的宽和高属性
                firstBtn.label = "|<";
                firstBtn.setStyle("fontSize",9);
                firstBtn.parent.width = firstBtn.parent.parent.width ;
                firstBtn.width = ( firstBtn.parent.width / 4 ) ;
                firstBtn.height= 20;
                
                preBtn.label = "<";
                preBtn.parent.width = preBtn.parent.parent.width ;
                preBtn.width = (preBtn.parent.width / 4) ;
                preBtn.height= 20;
                
                nextBtn.label = ">";
                nextBtn.parent.width = nextBtn.parent.parent.width ;
                nextBtn.width = (nextBtn.parent.width / 4) ;
                nextBtn.height= 20;
                
                lastBtn.label = ">|";
                lastBtn.setStyle("fontSize",9);
                lastBtn.parent.width = lastBtn.parent.parent.width ;
                lastBtn.width = ( lastBtn.parent.width / 4 ) ;
                lastBtn.height= 20;
                
                firstBtn.addEventListener(MouseEvent.CLICK,firstPage);
                preBtn.addEventListener(MouseEvent.CLICK,prePage);
                nextBtn.addEventListener(MouseEvent.CLICK,nextPage);
                lastBtn.addEventListener(MouseEvent.CLICK,lastPage);
                
                //sql的初始化,这里我在组件里写死了,加上get和set方法后应该可以外部传入,自己没有试。
                sql = " select a0100,a0101 from person where 1 = 1 " ;
                //获取总记录数的请求,根据业务要求可重新设置
                recordsService.url = "http://localhost:8080/Test/getDatas.htm";
                //获取list中数据的请求,根据业务要求可重新设置
                httpService.url = "http://localhost:8080/Test/getDatas.htm";
                
            }
            
            //第一页
            private function firstPage(e:MouseEvent):void {
                start = 1;
                httpService.send({"sql":this.getSQL(sql,start,limit)});
            }
            //上一页
            private function prePage(e:MouseEvent):void {
                if(start <= 1){
                    start = 1;
                } else {
                    start --;
                }
                httpService.send({"sql":this.getSQL(sql,start,limit)});
            }
            //下一页
            private function nextPage(e:MouseEvent):void {
                if(start >= totalPage){
                    start = totalPage;
                } else {
                    start ++;
                }
                httpService.send({"sql":this.getSQL(sql,start,limit)});
            }
            //最后一页
            private function lastPage(e:MouseEvent):void {
                start  = totalPage;
                httpService.send({"sql":this.getSQL(sql,start,limit)});
            }
            //键盘操作的处理
            private function up(e:KeyboardEvent):void {
                if(datas.length <= 0){
                    return;
                }
                if(!list.visible){
                    this.list.visible = true;
                    this.bbar.visible = true;
                }
                //向右
                if(e.keyCode == Keyboard.RIGHT){
                    if(list.visible == false){
                        list.visible = true;
                        bbar.visible = true;
                        return;
                    }
                    this.input.selectRange(this.input.text.length,this.input.text.length);
                    if(start >= totalPage){
                        start = totalPage;
                    } else {
                        start ++;
                    }
                    httpService.send({"sql":this.getSQL(sql,start,limit)});
                }else if(e.keyCode == Keyboard.LEFT){ //向左
                    if(!list.visible){
                        list.visible = true;
                        bbar.visible = true;
                        return;
                    }
                    //设置textinput中的鼠标始终在最左侧
                    this.input.selectRange(this.input.text.length,this.input.text.length);
                    if(start <= 1){
                        start = 1;
                    } else {
                        start --;
                    }
                    httpService.send({"sql":this.getSQL(sql,start,limit)});
                }else if(e.keyCode == Keyboard.DOWN){//向下
                    this.cursorManager.hideCursor();
                    if(this.list.selectedIndex == datas.length - 1){
                        this.list.selectedIndex = 0;
                        this.list.ensureIndexIsVisible(this.list.selectedIndex);
                    } else {
                        this.list.selectedIndex ++;
                        this.list.ensureIndexIsVisible(this.list.selectedIndex);
                    }
                    this.list.visible = true;
                    this.bbar.visible = true;
                    if(same){
                        this.input.text = this.list.selectedItem.A0101;
                    }
                    this.input.selectRange(this.input.text.length,this.input.text.length);
                } else if(e.keyCode == Keyboard.UP){//向上
                    this.cursorManager.hideCursor();
                    if(this.list.selectedIndex <= 0){
                        this.list.selectedIndex = datas.length - 1;
                        this.list.ensureIndexIsVisible(this.list.selectedIndex);
                    } else {
                        this.list.selectedIndex --;
                        //设置list的滚动条跟随滑动
                        this.list.ensureIndexIsVisible(this.list.selectedIndex);
                    }
                    this.list.visible = true;
                    this.bbar.visible = true;
                    if(same){
                        this.input.text = this.list.selectedItem.A0101;
                    }
                    this.input.selectRange(this.input.text.length,this.input.text.length);
                } else if(e.keyCode == Keyboard.ENTER){//回车键
                    list.visible = false;
                    bbar.visible = false;
                    if(list.selectedItem != null){
                        //注意:此处的A0101为查询的字段
                        this.input.text = this.list.selectedItem.A0101;
                        this.input.selectRange(this.input.text.length,this.input.text.length);
                    }
                }
            }
            
            private function clickItem(e:IndexChangeEvent):void {
                this.focusManager.setFocus(this.input);
                var item:Object = this.list.selectedItem;
                //注意:此处的A0101为查询的字段
                this.input.text = item.A0101;
                this.list.visible = false;
                this.bbar.visible = false;
            }
            private function outClick(e:MouseEvent):void {
                var mex:Number = e.stageX;
                var mey:Number = e.stageY;
                
                if((mex > this.input.x && mex < (this.input.x + this.input.width)) && (mey > (this.list.y + this.input.height) && mey < (this.list.height + this.list.y))){
                    if(!(this.list.visible)){
                        return;
                    }
                }
                
            }
            //计时器发送请求的操作
            private function timerFinished(e:TimerEvent):void {
                start = 1;
                var tempsql:String = "";
                if(input.text != ""){
                    tempsql = " and (a0101 like '" + input.text + "%' or a0100 like '" + input.text + "%') " ;
                }
                var csql:String = " select count(1) records from ( " + sql + tempsql + " ) ";
                recordsService.send({"sql":csql});
            }
            //textinput改变时的操作
            private function onChange(e:TextOperationEvent):void {
                list.visible = true;
                bbar.visible = true;
                if(timer.running){
                    timer.reset();
                    timer.start();
                } else {
                    timer.start();
                }
            }
            //list点击时的操作
            private function clickList(e:MouseEvent):void {
                this.list.visible = true;
                this.focusManager.setFocus(this.list);
            }
            //请求list中的数据完成时的回调
            private function success():void {
                var rs:String = httpService.lastResult.toString();
                var json:JSONDecoder = new JSONDecoder(rs,true);
                var list:Array = json.getValue();
                datas = new ArrayCollection(list);
                this.input.selectRange(this.input.text.length,this.input.text.length);
            }
            //请求总页数完成时的回调
            private function recordsResult():void {
                this.input.selectRange(this.input.text.length,this.input.text.length);
                var rs:String = recordsService.lastResult.toString();
                var json:JSONDecoder = new JSONDecoder(rs,true);
                var list:Array = json.getValue();
                records = list[0].RECORDS;
                totalPage = Math.floor((records - 1) / limit) + 1;
                httpService.send({"sql":this.getSQL(sql,start,limit)});
            }
            
            private function failure():void {
                
            }
            
            private function focusIn(e:FocusEvent):void {
                if(!(this.list.visible)){
                    this.list.visible = true;
                    this.bbar.visible = true;
                }
            }
            
            private function focusOut(e:FocusEvent):void {
                this.list.visible = false;
                this.bbar.visible = false;
            }
            //发送请求前,对sql的业务处理
            private function getSQL(sql:String,start:int,limit:int):String {
                var tempsql:String = "";
                if(input.text != ""){
                    tempsql = " and (a0101 like '" + input.text + "%' or a0100 like '" + input.text + "%') " ;
                }
                var fsql:String = "";
                fsql = "SELECT * FROM                                             ";
                fsql += "(                                                         ";
                fsql += "    SELECT A.*, ROWNUM RN FROM                               ";
                fsql += "    (                                                        ";
                fsql += sql + tempsql;
                fsql += "    ) A                                                      ";
                fsql += "    WHERE ROWNUM <=  " + start * limit;
                fsql += ")                                                         ";
                fsql += "WHERE RN >  " + ((start - 1) * limit);
                return fsql;
            }

            public function get sql():String
            {
                return _sql;
            }

            public function set sql(value:String):void
            {
                _sql = value;
            }            
        ]]>
    </fx:Script>
    <s:VGroup gap="0">
            <s:TextInput id="input"/>
            <s:List id="list" dataProvider="{datas}" labelField="A0101"></s:List>
            <s:BorderContainer id="bbar" height="22">
                <s:HGroup gap="0" width="{this.parent.width}">
                    <mx:LinkButton id="firstBtn"/>
                    <mx:LinkButton id="preBtn"/>
                    <mx:LinkButton id="nextBtn"/>
                    <mx:LinkButton id="lastBtn"/>
                    <mx:Text id="pagerBtn" text="{ start + '/' + totalPage}"/>
                </s:HGroup>
            </s:BorderContainer>    
    </s:VGroup>
</s:Group>
后台的代码用spring mvc实现,具体代码如下:

@RequestMapping("/getDatas.htm")
    public String getDatas(String sql,HttpServletResponse response){
        System.out.println(sql);
        List<Map<String,Object>> list = baseDao.queryForList(sql);
        JSONArray json = new JSONArray();
        json.addAll(list);
        response.setCharacterEncoding("utf-8");
        try {
            response.getWriter().println(json.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

还有小bug,但基本没有太大的问题。希望感兴趣的朋友指正。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多