需要将内部函数绑定到元素的click事件

时间:2016-04-07 11:17:20

标签: javascript knockout.js

我需要使用我在initMap函数中定义的“resetMap”函数(谷歌地图的回调函数),以绑定到重置按钮。现在它无法使用,因为它不在全球范围内。 如果我将此函数移动到全局范围,则其项目(例如mapOptions.center setzoom等)将是未定义的。

这是我的脚本文件

var map;

/* Hardcoding 5 airport locations - our data - model*/
var airports = [
    {
        title: "Calicut International Airport",
        lat: 11.13691,
        lng: 75.95098,
        streetAddress: "Karipur",
        cityAddress: "Malappuram, Kerala",
        visible: ko.observable(true),
        id: "nav0",
        showIt: true
    },
    {
        title: "Chennai International Airport",
        lat: 12.9920434,
        lng: 80.1631409,
        streetAddress: "Meenambakkam",
        cityAddress: "Chennai, Tamil Nadu",
        visible: ko.observable(true),
        id: "nav1",
        showIt: true
    },
    {
        title: "Trivandrum International Airport",
        lat: 8.4829722,
        lng: 76.909139,
        streetAddress: "Vallakkadavu",
        cityAddress: "Thiruvananthapuram, Kerala",
        visible: ko.observable(true),
        id: "nav2",
        showIt: true
    },
    {
        title: "Cochin International Airport",
        lat: 10.15178,
        lng: 76.39296,
        streetAddress: "Nedumbassery",
        cityAddress: "Kochi, Kerala",
        visible: ko.observable(true),
        id: "nav3",
        showIt: true
    },
    {
        title: "Kempegowda International Airport",
        lat: 13.2143948,
        lng: 77.6896124,
        streetAddress: "Devanahalli",
        cityAddress: "Bengaluru, Karnataka",
        visible: ko.observable(true),
        id: "nav4",
        showIt: true
    }
];


/* Initializing map, markers */
function initMap() {

    var myLatlng = new google.maps.LatLng(13.2143948, 77.6896124);
    var mapOptions = {
        zoom: 6,
        disableDefaultUI: true
    };

    var bounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(8.4829722, 76.909139), //SW coordinates here
        new google.maps.LatLng(13.2143948, 77.6896124) //NE coordinates here
    );

    map = new google.maps.Map(document.getElementById("map"), mapOptions);
    map.fitBounds(bounds);

    setMarkers(airports);
    setMapWithMarker();

    /* Function to reset the map zoom and set center */
    function resetMap() {
        map.setCenter(mapOptions.center);
        map.setZoom(6);
    }

    $(window).resize(function(){
        map.setCenter(mapOptions.center);
    });
}

/* Controlling the visibility of marker based on the 'showIt' property */
function setMapWithMarker() {
    for (var i = 0; i < airports.length; i++) {
        if(airports[i].showIt === true) {
            airports[i].locMarker.setMap(map);
        } else {
            airports[i].locMarker.setMap(null);
        }
    }
}

/* Setting markers on map and attaching content to each of their info windows */
function setMarkers(location) {
    var img = 'img/airport.png';
    for (var i = 0; i < location.length; i++) {
        location[i].locMarker = new google.maps.Marker({
            position: new google.maps.LatLng(location[i].lat, location[i].lng),
            map: map,
            animation: google.maps.Animation.DROP,
            title: location.title,
            icon:img
        });

        var airportTitle = location[i].title;
        var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' +
        airportTitle + '&format=json&callback=wikiCallback';

        (function(i){
            var wikiRequestTimeout = setTimeout(function() {
                $('.show-error').html('ERROR: Failed to load wikipedia data - Airport details will not show up! Sorry for the inconvenience caused.');
            }, 5000);

            $.ajax({
                url: wikiUrl,
                dataType: "jsonp"
            }).done(function(response){
                var article = response[2][0];
                    location[i].contentString =
                    '<strong>'+ location[i].title + '</strong><br><p>' + location[i].streetAddress
                    + '<br>' + location[i].cityAddress + '<br></p><p>' + article +
                    '</p><p>Source: Wikipedia</p>';
                    clearTimeout(wikiRequestTimeout);
            });
        })(i);

        /* info window initialization and setting content to each marker's info window */
        var infowindow = new google.maps.InfoWindow({});

        new google.maps.event.addListener(location[i].locMarker, 'click',
            (function(airport, i) { return function() {
                airport.setAnimation(google.maps.Animation.BOUNCE);
                setTimeout(function() {
                    airport.setAnimation(null);
                }, 2400);
                infowindow.setContent(location[i].contentString);
                infowindow.open(map,this);
                map.setZoom(15);
                map.setCenter(airport.getPosition());
            };
        })(location[i].locMarker, i));

        /* info window call when clicked on airport menu item */
        var searchNav = $('#nav' + i);
        searchNav.click((function(airport, i) {
            return function() {
                airport.setAnimation(google.maps.Animation.BOUNCE);
                setTimeout(function() {
                    airport.setAnimation(null);
                }, 2200);
                infowindow.setContent(location[i].contentString);
                infowindow.open(map,airport);
                map.setZoom(15);
                map.setCenter(airport.getPosition());
            };
        })(location[i].locMarker, i));
    }
}

/* Function for toggling the menu */
function slideToggle() {
    $(this).toggleClass('toggled');
    $( "#listing" ).toggle( "slow", function() {
        // Animation complete.
    });
}

/* Our view model */
function viewModel() {
    var self = this;
    this.locMarkerSearch = ko.observable('');
    ko.computed(function() {
        var search = self.locMarkerSearch().toLowerCase();
        return ko.utils.arrayFilter(airports, function(airport) {
            if (airport.title.toLowerCase().indexOf(search) >= 0) {
                airport.showIt = true;
                return airport.visible(true);
            } else {
                airport.showIt = false;
                setMapWithMarker();
                return airport.visible(false);
            }
        });
    });
};

// Activates knockout.js
ko.applyBindings(new viewModel());

我需要在index.html中绑定函数

<footer>
  <button id="reset" data-bind="click: resetMap">Reset Zoom to center</button>
</footer>

<script src="js/lib/knockout-3.4.0.js"></script>
<script src="js/script.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDVOVW9WT7QaVlFYDkE7K2Qm-AvSS02YrM&callback=initMap" async defer onerror="googleError()"></script>

如何解决此问题?提前谢谢..

1 个答案:

答案 0 :(得分:1)

您尚未向我们展示viewModel使用initMap的方式,但从根本上说,initMap需要向外界提供resetMap。一种方法是返回它:

function initMap() {
    // ...
    function resetMap() {
    }
    // ...
    return resetMap;
}

然后让viewModel中的代码将其放在视图模型上:

function viewModel() {
    this.resetMap = initMap(); // I assume you're calling this indirectly; whatever
}

然后resetMap可以访问它所需要的内容,并且它位于视图模型上,因此可以绑定它。