延迟加载自动完成数据列表angularjs

时间:2019-09-12 08:37:21

标签: jquery html angularjs autocomplete

我有一份工作来重构一些代码以提高对IE 11的偏好, 所需的改进之一是对自动完成输入进行一些延迟加载,因为IE 11在渲染array并包含600个项目时不算太重。

我在某些约束下工作:

1. I have 4 hours to done the job (it's mean that there is no time to massive changes)
2. AngularJs version 1.3.1
3. jQuery version 1.6.8
4. The page is hosting on salesforce (it's not changing anything because it's run html and angularjs).

这是问题的GIFlink to GIF

我成功完成了一些延迟加载,但是由于某种原因(我不知道要解释它)无法正常工作。 仅在我将焦点移到输入字段并再次将其聚焦后,自动完成渲染的列表。

这是 HTML代码

<input type="text" id="ddProductAutoCompleteInput" name="product" class="selectBoxTom" data-ng-model="item.onlineProd" datalist="t_productsList_DDP" placeholder="All Products"  />
<datalist id="t_productsList_DDP"  size="5" style="overflow-y: scroll">
     <option ng-repeat="prod in productList | limitTo:totalLimit track by $index" value="{{prod.Tapi_Online_Product_Name__c}}" ngc-done="'scope.setAutoCompletProdectDwonloadDoc'"/>
</datalist>      

这是 AngularJs代码

$scope.setAutoCompletProdectDwonloadDoc = function()//sourceList)
 {  
            var flag = true;
            var elem = jQuery("#ddProductAutoCompleteInput");
            var list = jQuery("#t_productsList_DDP");
            $scope.totalLimit = 50;
            jQuery('.ui-autocomplete').scroll(function(){
                if (jQuery(this).scrollTop() + jQuery(this).innerHeight() >= jQuery(this)[0].scrollHeight) {
                    $scope.totalLimit += 10;
                    elem.autocomplete.focusout();
                }
            })

            elem.autocomplete({
                source: list.children().map(function(){return jQuery(this).val();}).get(),//sourceList,
                minLength: 0,
                search: function(event,ui){
                    jQuery(this).data("autocomplete").menu.bindings = $();
                },
                select: function (event, ui)
                {
                  var valueP = ui.item.value;
                  flag = false;
                  elem.autocomplete('close');
                  $scope.$apply(function()
                  {
                   $scope.item.onlineProd = valueP;
                   angular.forEach($scope.docTypeList, function(docType){
                                  docType.selected = false});
                   $scope.tempList.length = 0;
                   $scope.filterd = 'false';

                  });
                },
                open:function (event, ui)
                {
                    // Try to select the first one if it's the only one
                    var $children = jQuery(this).data('autocomplete').menu.element.children();
                    if ($children.size() == 1)
                    {
                    }/*else{
                        var item = '';
                        var childs = $children.toArray();
                        for(var i = 0; i< $children.length; i++){

                            if(event.target.value.toLowerCase().trim() === childs[i].innerText.toLowerCase().trim()){
                                item = $children.eq(i);
                            }
                        }
                        if(item !== '')
                            jQuery(this).data('autocomplete').menu.focus(null, item);
                    }*/
                }
            }).focus(function(){
                if (flag)
                {
                    jQuery(this).autocomplete('search',jQuery(this).val())
                    flag = false;
                }else{
                    elem.autocomplete('close');
                    flag = true;
                return false;
                }
            }).focusout(function(){flag = true; return false;})

            $scope.totalLimit = 50;

  };

除了“延迟加载”将正常工作之外,我是这样-这意味着当我向下滚动列表时-还会有10多个项目呈现到列表中。enter link description here

1 个答案:

答案 0 :(得分:0)

在深入研究之后,我找到了解决方案 解决方案的参考是     http://jsfiddle.net/LesignButure/

所以我这个问题的主要问题是我必须处理现有代码而不要更改它,只需在其中添加一些脚本即可。

该页面未呈现的错误是错误的,因为自动完成的生命周期是- 1. totalLimit设置列表限制 2. setAutoCompletProdectDwonloadDoc被激活并配置自动完成的结构 3.列表被渲染 4.向下滚动后-totalLimit变小,并且呈现了组件,但列表未更改,原因是自动完成的“打开”功能已运行。 5.重新单击输入字段后,将显示新列表

所以我所做的更改在这里:

/*product*/
 $scope.setAutoCompletProdectDwonloadDoc = function()//sourceList)
 {
     var flag = true;
     var elem = jQuery("#ddProductAutoCompleteInput");
     var list = jQuery("#t_productsList_DDP");


/**
     elem.autocomplete({
         source: list.children().map(function () { return jQuery(this).val(); }).get(),//sourceList,
         minLength: 0,
         search: function (event, ui) {
             jQuery(this).data("autocomplete").menu.bindings = $();
         },
         select: function (event, ui) {
             var valueP = ui.item.value;
             flag = false;
             elem.autocomplete('close');
             $scope.$apply(function () {
                 $scope.item.onlineProd = valueP;
                 angular.forEach($scope.docTypeList, function (docType) {
                     docType.selected = false
                 });
                 $scope.tempList.length = 0;
                 $scope.filterd = 'false';

             });
         },
         open: function (event, ui) {
             var $children = jQuery(this).data('autocomplete').menu.element.children();
         }
         }).focus(function () {
             if (flag) {
                 jQuery(this).autocomplete('search', jQuery(this).val())
                 flag = false;
             } else {
                 elem.autocomplete('close');
                 flag = true;
                 return false;
             }
         }).focusout(function () { flag = true; return false; })

**/
        elem.autocomplete({
            source: list.children().map(function () { return jQuery(this).val(); }).get(),
            minLength: 0,
            delay: 0,
            search: function (event, ui) {
                jQuery(this).data("autocomplete").menu.bindings = $();
            },
            select: function (event, ui) {
                 var valueP = ui.item.value;
                 flag = false;
                 elem.autocomplete('close');
                 $scope.$apply(function () {
                     $scope.item.onlineProd = valueP;
                     angular.forEach($scope.docTypeList, function (docType) {
                         docType.selected = false
                     });
                     $scope.tempList.length = 0;
                     $scope.filterd = 'false';

                 });
             },
             open: function (event, ui) {
                 var $children = jQuery(this).data('autocomplete').menu.element.children();
            }
        }).focus(function () {
            //reset result list's pageindex when focus on
            window.pageIndex = 0;
            $(this).autocomplete("search");
        }).focusout(function () { flag = true; return false; });


        $.extend($.ui.autocomplete.prototype, {
                _renderMenu: function (ul, items) {
                    //remove scroll event to prevent attaching multiple scroll events to one container element
                    $(ul).unbind("scroll");
                    var self = this;
                    self._scrollMenu(ul, items);
                },
                _scrollMenu: function (ul, items) {
                    var maxShow = 999;
                    if(items.length > 400)
                        maxShow = 20;
                    var self = this;
                    var results = [];
                    var pages = Math.ceil(items.length / maxShow);
                    results = items.slice(0, maxShow);

                    if (pages > 1) {
                        $(ul).scroll(function () {
                            if (isScrollbarBottom($(ul))) {
                                ++window.pageIndex;
                                if (window.pageIndex >= pages) return;

                                results = items.slice(window.pageIndex * maxShow, window.pageIndex * maxShow + maxShow);

                                //append item to ul
                                $.each(results, function (index, item) {
                                    self._renderItem(ul, item);
                                });
                                //refresh menu
                                self.menu.deactivate();
                                self.menu.refresh();
                                // size and position menu
                                ul.show();
                                self._resizeMenu();
                                ul.position($.extend({
                                    of: self.element
                                }, self.options.position));
                                if (self.options.autoFocus) {
                                    self.menu.next(new $.Event("mouseover"));
                                }
                            }
                        });
                    }

                    $.each(results, function (index, item) {
                        self._renderItem(ul, item);
                    });
                }
            });

            function isScrollbarBottom(container) {
                 var height = container.outerHeight();
                 var scrollHeight = container[0].scrollHeight;
                 var scrollTop = container.scrollTop();
                 if (scrollTop >= scrollHeight - height) {
                     return true;
                 }
                 return false;
             };
  };