2012-12-04 9 views
30

У меня есть карта листовка в рабочем состоянии. Он накладывает на карту ряд полигонов (через GeoJSON) и прикрепляет всплывающие окна к каждому полигону. Каждое всплывающее окно отображает информацию об этом многоугольнике.Нажмите ссылку внутри всплывающего окна и сделайте Javascript

Я хотел бы иметь внутри всплывающего окна ссылку, которая при нажатии запускает функцию javascript, которая тянет более мелкие полигоны через AJAX и показывает их.

Я не могу заставить скрипт поймать щелчок по ссылке через обычные события jQuery/Javascript. Вот что я имею в виду под нормальным (следующее не работает):

Часть bindPopup заключается в следующем. Он запускается на каждом полигоне, когда он сделан, и он всплывает правильно при нажатии на полигон. Он показывает ссылку, просто не будет запускать вышеуказанный код при нажатии.

var popupContent = "Basic Information..." + '<a class="smallPolygonLink" href="#">Click here to see the smaller polygons</a>'; 
layer.bindPopup(popupContent); 

Вот пример JSFiddle, иллюстрирующий пример, хотя и в гораздо более простой форме. http://jsfiddle.net/2XfVc/4/

ответ

41

Элемент связи внутри всплывающего окна динамически генерируется из вашей разметки каждый раз, когда всплывающее окно открывается. Это означает, что ссылка не существует, когда вы пытаетесь связать обработчик с ней.

Идеальный подход здесь заключается в использовании on для делегирования обработки событий во всплывающем элементе или его предке. К сожалению, всплывающее окно предотвращает распространение событий, поэтому делегирование обработки событий для любых статических элементов вне всплывающего окна не будет работать.

Что вы можете сделать, это предустановить ссылку, прикрепить обработчик, а затем передать его методу bindPopup.

var link = $('<a href="#" class="speciallink">TestLink</a>').click(function() { 
    alert("test"); 
})[0]; 
marker.bindPopup(link); 

Вот демонстрация: http://jsfiddle.net/2XfVc/7/

В общем, чтобы вставить какой-либо сложной разметки с несколькими обработчиками событий, использовать на следующие подходы:

// Create an element to hold all your text and markup 
var container = $('<div />'); 

// Delegate all event handling for the container itself and its contents to the container 
container.on('click', '.smallPolygonLink', function() { 
    ... 
}); 

// Insert whatever you want into the container, using whichever approach you prefer 
container.html("This is a link: <a href='#' class='smallPolygonLink'>Click me</a>."); 
container.append($('<span class="bold">').text(" :)")) 

// Insert the container into the popup 
marker.bindPopup(container[0]); 

Вот демо: http://jsfiddle.net/8Lnt4/

См. this Git issue для получения дополнительной информации о распространении события в всплывающих окнах листов.

+0

Как бы я изменить это, чтобы добавить текст или содержание, которое не кликабельны? Например. Имя: xxxx, Возраст: xxxx, Нажмите ссылку для получения более подробной информации. Если только слово «ссылка» является кликабельным. Кроме того, что делает часть [0]? Я не могу найти ссылку в jQuery click api. – Josh

+2

@Josh Просто добавьте другие элементы вместе с кликабельными. Вот демонстрация: http://jsfiddle.net/2XfVc/8/. Часть '[0]' просто получает узел DOM из коллекции jQuery, так как листочка принимает стандартные узлы DOM, но не коллекции jQuery. –

+0

Awesome. Я изменил его на '.html()' вместо '.text()', чтобы появилось некоторое форматирование html, но в остальном это было идеально. Благодарю. – Josh

1

Вы можете использовать jQuery для выбора элемента canvas, но вам придется использовать его собственные методы в пределах холста. Хорошим стартом будет https://developer.mozilla.org/en/canvas_tutorial.

21

В то время как оболочка содержимого всплывающих окон предотвращает распространение событий, события внутри всплывающей внутренней разметки распространяются просто отлично. Вы можете добавлять события во всплывающие элементы, когда они отображаются на карте (и стали частью DOM). Просто наблюдайте за листингом popupopen.

var map = L.map('map').setView([51.505, 10], 7); //for example 

//the .on() here is part of leaflet 
map.on('popupopen', function() { 
    $('a .smallPolygonLink').click(function(e){ 
    console.log("One of the many Small Polygon Links was clicked"); 
    }); 
}); 

http://jsfiddle.net/tJGQ7/2/

Это работает как шарм для меня. Если в вашем всплывающем окне нет 'a .smallPolygonLink', то указанный выше код ничего не делает. Этот код запускается при каждом запуске всплывающего окна. Однако вам не нужно беспокоиться о том, что он прикрепляет более одного обработчика к элементу, поскольку, когда всплывающее окно закрывается, узлы DOM отбрасываются.

Существует гораздо более общий способ сделать это. Однако он включает eval(). Используйте на свой страх и риск. Но когда AJAXloading частичных страниц, содержащих JS запустить те же риски, поэтому для назидания я представляю «выполнение JS внутри вашего рекламного листка всплывающих окон»:

map.on('popupopen', function(){ 
    var cont = document.getElementsByClassName('leaflet-popup-content')[0];  
    var lst = cont.getElementsByTagName('script'); 
    for (var i=0; i<lst.length;i++) { 
     eval(lst[i].innerText) 
    } 
}); 

демо: http://jsfiddle.net/tJGQ7/4/

Теперь вы можете написать:

var popup_content = 'Testing the Link: <a href="#" class="speciallink">TestLink</a><script> $(".speciallink").on("click", function(){alert("hello from inside the popup")});</script>'; 

marker.bindPopup(popup_content); 
+0

Определенно лучший ответ здесь - нет необходимости в работе :-) –

+0

yep, должен быть лучшим ответом здесь. приятное решение! –

+0

Проблема в том, что вы повторно прикрепляете обработчик событий каждый раз, когда всплывающее окно открыто, что сейчас неэффективно и не работает, как только вы посмотрите на вставку более сложных структур с несколькими обработчиками. Идеальный подход здесь состоял в том, чтобы делегировать обработку событий во всплывающем элементе или его предке, что я изначально предложил в своем ответе. Однако я обнаружил, что листовки нарушают распространение событий, что означает, что 'on' не будет работать. Второй лучший подход заключается в том, чтобы связать любую функцию обработки событий точно * один раз * с элементом контейнера и вставить. –

3

Я столкнулся с этой проблемой, попробовал решение выше. Но это не сработало для меня. Нашел следующее довольно простое решение для jQuery.

// add your marker to the map 
var my_marker = new L.marker([51.2323, 4.1231], {icon: my_icon}); 
var popup = L.popup().setContent('<a class="click" href="#">click</a>'); 
my_marker.addTo(map).bindPopup(popup); 

// later on 
jQuery("body").on('click','a.click', function(e){ 
    e.preventDefault(); 
    alert('clicked'); 
}); 
0

Вы можете проверить внутренние свойства из popup объекта, в том числе _wrapper и т.д.

map.on('popupopen', _bindPopupClick); 
map.on('popupclose', _unbindPopupClick); 

var _bindPopupClick = function (e) { 
    if (e.popup) { 
     e.popup._wrapper.addEventListener('click', _bindPopupClickHandler); 
    } 
}; 
var _unbindPopupClick = function (e) { 
    if (e.popup) { 
     e.popup._wrapper.removeEventListener('click', _bindPopupClickHandler); 
    } 
}` 
4

Вот что я нашел на MapBox официального вебсайте: Create a click event in a marker popup with Mapbox.js and jQuery. Комментарий объясняет, почему мы говорим $('#map') вместо $('#mybutton').

var marker = L.marker([43.6475, -79.3838], { 
    icon: L.mapbox.marker.icon({ 
    'marker-color': '#9c89cc' 
    }) 
}) 
.bindPopup('<button class="trigger">Say hi</button>') 
.addTo(map); 
//The HTML we put in bindPopup doesn't exist yet, so we can't just say 
//$('#mybutton'). Instead, we listen for click events on the map element which will bubble up from the tooltip, once it's created and someone clicks on it. 

$('#map').on('click', '.trigger', function() { 
alert('Hello from Toronto!');}); 
0

MapBox JavaScript библиотека имеет событие:

bindPopup('<button class="trigger">Say hi</button>'); 
addTo(map); 

$('#map').on('click', '.trigger', function() { 
    alert('Hello from Toronto!'); 
}); 

https://www.mapbox.com/mapbox.js/example/v1.0.0/clicks-in-popups/

+0

не сбрасывайте код, объясните это. хорошее объяснение важно понять, почему ваше предлагаемое решение решит проблему OP. –