【问题标题】:Marker search function in KnockoutKnockout 中的标记搜索功能
【发布时间】:2015-07-02 06:24:22
【问题描述】:

我正在开发一个 KnockoutJS 应用程序并尝试实现标记搜索功能。这个想法是使用名称在搜索栏上执行搜索,相应的标记将与列出的显示一起过滤。以下函数进行过滤 -

my.myDataFilter = function(){

        my.FilteredList = ko.pureComputed(function() {
                if(my.query() === "") {
                  return my.points; 
                } 

                else {
                  return ko.utils.arrayFilter(my.points(), function(item) {
                      return item.name().toLowerCase().indexOf(my.query().toLowerCase())>-1;
                });
            }         
        }, this);

    }

搜索栏在 HTML 中 -

<header> 
                <form action="#"> 
                    <input class="search" placeholder="Search…" type="search" name="q" data-bind="value: my.query, valueUpdate: 'keyup'" autocomplete="off"> 
                </form> 
            </header> 

和可能的展示 -

<div class="con"> 
                <h3>Filtered List</h3>
                <ul data-bind="template: {name:'beer', foreach: my.FilteredList}"> 
                </ul> 
            </div> 

my.loadMap 函数如下 -

my.loadMap = function(item){ 
        my.pusMarkerData(item);

    }

推送标记数据的函数是-

my.query = ko.observable("");

    my.pusMarkerData = function(item){

        // console.log(item);
        my.points = ko.observableArray();  
        for (var j = 0; j < item.length; j++){
            my.points.push( new my.mapMarker( item[j]['category'], item[j]['name'], item[j]['lat'], item[j]['lon']));
        } 
    }

我的问题是 -

  1. 在获取 my.FilteredList 后如何调用 my.loadMap(testValues) 以显示过滤后的标记?
  2. 使用搜索栏的过滤功能并不是我想要实现的。以下是 jsFiddle 中意图的示例:http://jsfiddle.net/mythical/XJEzc/

谢谢

index.html

<!DOCTYPE html>

<head>
    <meta charset="UTF-8">
    <title>Single page map application</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
</head>

<body>
        <header> 
            <form action="#"> 
                <input class="search" placeholder="Search…" type="search" name="q" data-bind="value: my.query, valueUpdate: 'keyup'" autocomplete="off"> 
            </form> 
        </header> 

        <div class="content"> 
            <h3>Complete List</h3>
            <ul data-bind="template: {name:'beer', foreach:my.points}"> 
            </ul> 
        </div>

        <div class="con"> 
            <h3>Filtered List</h3>
            <ul data-bind="template: {name:'beer', foreach: my.FilteredList}"> 
            </ul> 
        </div> 

        <script type="text/html" id="beer"> 
            <li>
                <strong data-bind="text: category"></strong>
            </br>
                <span data-bind="text:name"></span>
                <span data-bind="text: lat"></span>
                <span data-bind="text: lon"></span>
            </li>
        </script> 

        <div id="map"></div> 
        <div id="eat" data-bind="template: { name: 'pointsTmpl', foreach: my.points }"></div>
        <script id="pointsTmpl" type="text/html">
            <p>
                <span data-bind="text: category"></span>; 
                <span data-bind="text: lat"></span>;
                <span data-bind="text: lon"></span>
            </p>
        </script>

        <!-- list of the imports  -->

        <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script>                
        <script src="js/lib/knockout-3.2.0.js"></script>        
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
        <script src="js/data.js"></script>
        <script src="js/app.js"></script>

        <!-- 
            <script src="js/lib/jQuery.js"></script>
            <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
            <script data-require="knockout@*" data-semver="3.3.0" src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script> 
        -->

</body>

app.js

$( function() {

my.createMap = function(){

    var myOptions = {
        zoom: my.sampleData.zoomLevel,
        center: new google.maps.LatLng( my.sampleData.centerCoordinates[0], my.sampleData.centerCoordinates[1] ),

        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    // map = new google.maps.Map(document.getElementById('map'), myOptions); // vanilla JS
    my.map = new google.maps.Map( $('#map')[0], myOptions); // using jQuery
}

my.mapMarker = function ( category, name, lat, lon) {

    this.category = ko.observable(category);
    this.name = ko.observable(name);
    this.lat = ko.observable(lat);
    this.lon = ko.observable(lon);

    var marker = new google.maps.Marker({

        position: new google.maps.LatLng(lat, lon),
        title: name,
        animation: google.maps.Animation.DROP, 
        map: my.map,
        draggable: false
    });

    // draging for the markers 
    google.maps.event.addListener(marker, 'drag', function() {
        var pos = marker.getPosition();
        this.lat(pos.lat());
        this.lon(pos.lng());
    }.bind(this));

    google.maps.event.addListener(marker, 'dragend', function() {
        var pos = marker.getPosition();
        this.lat(pos.lat());
        this.lon(pos.lng());
    }.bind(this)); 
}

my.query = ko.observable("");

my.pusMarkerData = function(item){

    // console.log(item);
    my.points = ko.observableArray();  
    for (var j = 0; j < item.length; j++){
        my.points.push( new my.mapMarker( item[j]['category'], item[j]['name'], item[j]['lat'], item[j]['lon']));
    } 
}

my.myDataFilter = function(){

    my.FilteredList = ko.pureComputed(function() {
            if(my.query() === "") {
              return my.points; 
            } 

            else {
              return ko.utils.arrayFilter(my.points(), function(item) {
                  return item.name().toLowerCase().indexOf(my.query().toLowerCase())>-1;
            });
        }         
    }, this);

}

my.loadMap = function(item){ 
    my.pusMarkerData(item);      
}

my.vm = function (){
    my.loadMap( my.sampleData.geoCoordinates ); 
} 

var test = new my.vm();

my.createMap();
ko.applyBindings(my.vm);

});

data.js

var my = my || { }; //my namespace

my.dataservice = (function (my) {

    "use strict";
    var getDataSet = function () {
        return my.sampleData;
    };

    return {
        getData: getDataSet
    };
})(my);

my.sampleData = (function (my) {

    "use strict";

    var data = {

        geoCoordinates : [

            { 'category':'Movie', 'name': "A beautiful mind", 'lat':25.758199, 'lon':-80.373668},
            {'category':'Movie', "name":  "Fight club",'lat':25.756769, 'lon':-80.369463},
            {'category':'TV shows', "name": "House of cards",'lat':25.754064, 'lon':-80.373582} 
        ],
        centerCoordinates : [25.754296, -80.377531],
        zoomLevel : 16
    }

    return {
        geoCoordinates : data.geoCoordinates,
        centerCoordinates: data.centerCoordinates,
        zoomLevel: data.zoomLevel
    };

})(my);

【问题讨论】:

  • 你在问什么?有什么不工作吗?
  • aquinas @我想在应用程序的右上角提供一个使用名称(my.sampleData.geoCoordinates.name)的搜索功能。因此,当您开始在搜索栏中输入姓名的前几个字母时,列表中的其他选项将被过滤掉。
  • 我现在更新了问题。

标签: javascript knockout.js


【解决方案1】:

您的问题只是一大堵代码。很多东西必须改变。看看这个:

http://plnkr.co/edit/txUxPhvR9V8xi2pkcRli?p=preview

你想做的基本事情是:

1) 将您的列表绑定到计算属性:像这样:

<div class="content">
    <ul data-bind="template: {name:'beer', foreach:my.FilteredList}">
    </ul>
</div>

2) 将计算属性创建为完整列表的过滤版本:

my.FilteredList = ko.computed(function() {
   if (my.query() === "") {
      return my.points;
   } 
   else {
     return ko.utils.arrayFilter(my.points(), function(item) {
        return item.name().toLowerCase().indexOf(my.query().toLowerCase()) > -1;
   });
};

3) 不要将变量命名为:“啤酒”。

【讨论】:

  • 非常感谢您的帮助。
猜你喜欢
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 2021-03-22
  • 2020-03-15
  • 2011-06-24
  • 2013-08-15
相关资源
最近更新 更多