Клуб API Карт

Снова про открытие балуна в коллекции меток

ilravil
28 марта 2013, 10:10

Как ни странно, но не смог найти как создать индексированную или поименованную коллекцию меток, с тем, чтобы открыть балун из внешнего меню. Пример с Музеями и Покушайками не совсем то, что нужно. Т.к. имеется динамическое внешнее меню, создаваемое независимо от карты и надо как-то привязаться к этим пунктам.
В API1  я это делал привязкой (bind) создаваемого объекта-метки к конкретному пункту меню.
В API2 так не получается: 

for (var key in shops[thisciti])
{
        var magaz=shops[thisciti][key];   
        var tel=(magaz['tel']=='')?'':"<br/>тел.: "+magaz['tel'];

myPlacemark=new ymaps.Placemark([magaz['lat'], magaz['long']],
{
balloonContent: magaz['name']+"
"+magaz['adres']+tel+"
"+magaz['www']+"
"+magaz['worktime']
},
{
preset: 'twirl#shopIcon'
}
);

myMap.geoObjects.add(myPlacemark);
$("[rel=shop_"+key+"]").bind("click", function () {
myPlacemark.balloon.open();
return false;
});

 

}

Если на карте 1 метка - работает, а если больше - то открывается балун последней.

Наверное надо объединить в коллекцию, но не смог найти - как сделать индексированную коллекцию, и как тогда обращаться по индексу

15 комментариев
Подписаться на комментарии к посту

Поищите в клубе записи с меткой "javascript" там у многих новичков возникают подобные проблемы, т.к. дело то вовсе не в АПИ (первом или втором) а в том что Вы не знаете язык.

Спасибо за содержательный ответ. Я понимаю, что тролль сейчас в моде, но хотелось бы по существу вопроса хотя бы от модераторов. Я работаю с javascript уже 12 лет (из своих 54) и прекрасно разбираюсь с ним. Но API2 это API2, а не JS, и в API1 во всех проектах всё работает.
Как модератор, вы могли бы спокойно дать ссылку на раздел, где подробно написано как делается индексированная коллекция, вместо того, чтобы упиваться собственным величием

Я ничем не упиваюсь, просто с подобным вопросом в наш клуб приходят каждую неделю. Еще раз, дело не в индексированной коллекции, а в том что подобный эффект возникает из-за того что обработчик события сработает гораздо позже выхода из цикла (если вообще сработает) И мне не понятно как за 12 лет работы с Javascript Вы этого так и не поняли

Вот пример работы в API1(делался года 4 назад)-
http://mskzoom.ru/crown/?gde
как видите, всё прекрасно работает
вот кусок кода с циклом:
 for (var i = 0; i < shops.length; i++) {
    map.addOverlay(createObject("Placemark", "my#style",shops[i].point, shops[i].name, shops[i].address, shops[i].phone, shops[i].id));
    };
       
        function createObject (type, style, point, sname, sadres, sphone, sid) {
            var allowObjects = ["Placemark", "Polyline", "Polygon"],
                index = YMaps.jQuery.inArray( type, allowObjects),
                constructor = allowObjects[(index == -1) ? 0 : index];
                description = sname+"
"+sadres+"
"+sphone || "";
               
           
            var object = new YMaps[constructor](point, {style: style, hideIcon: false, hasBalloon : !!description});
            object.description = description;
           
            $("#"+sid).bind("click", function () {
                    object.openBalloon();
                    return false;
                });
           
            YMaps.Events.observe(object,object.Events.Click, function () {
                Map_Content_Ref(sid);
            });
           
            return object;
        }

Ну так об этом и речь, у Вас же тут вызов функции "createObject" в этой версии,

и она, как и любая функция в Javascript, "замыкает" контекст.

Прочитайте уже наконец про замыкания в javascript и как они работают, а то так еще 12 лет проработаете наощупь.

Конкретно для вашего кода, чтобы Вы не решили что я опять троллю:

 

for (var key in shops[thisciti]){(function (key) {        var magaz=shops[thisciti][key];            var tel=(magaz['tel']=='')?'':"
тел.: "+magaz['tel'];myPlacemark=new ymaps.Placemark([magaz['lat'], magaz['long']], {balloonContent: magaz['name']+""+magaz['adres']+tel+""+magaz['www']+""+magaz['worktime']}, {preset: 'twirl#shopIcon'});myMap.geoObjects.add(myPlacemark);$("[rel=shop_"+key+"]").bind("click", function () {myPlacemark.balloon.open();return false;});}(key));}

 

PS: извините, если обидел, но вот такой уж я человек, говорю всё как есть.

не работает

дайте ссылку, я посмотрю

Несколько изменил код (по аналогии со старым в API1)- с замыканием
http://biopointcosmetics.ru/page/gde
(не работает в пункте "Махачкала")

    for (var key in shops[thisciti]){
        myMap.geoObjects.add(open_Pmark(key));
        }
   
    function open_Pmark(key){
        var magaz=shops[thisciti][key];   
        var tel=(magaz['tel']=='')?'':"
тел.: "+magaz['tel'];
  
        myPlacemark=new ymaps.Placemark([magaz['lat'], magaz['long']],
            {
                balloonContent: magaz['name']+"
"+magaz['adres']+tel+"
"+magaz['www']+"
"+magaz['worktime']
            },
            {
                preset: 'twirl#shopIcon'
            }
        );
       
        $("[rel=shop_"+key+"]").bind("click", function () {
        myPlacemark.balloon.open();
        $("[rel^=shop_]").removeClass('act');
        $(this).addClass('act');
        return false;
        });
       
        return myPlacemark;
    }

что не работает?

у меня открывает Махачкалу, в консоли ошибок нет

при клике в меню магазинов - открывается всегда только балун последнего пункта, а не того, что надо

Наверное потому что myPlacemark не создается каждый раз, зачем делать ее глобальной?

Вы просто меняете на нее ссылку и в конце концов она ссылается на последнюю метку.

Попробовал сделать неглобальной - (была глобальная, потому что в описании перехода на API2, в примерах она глобальная - я подумал, что это какое-то новшество) + надо объявить её локальной!:-)
Собственно, у меня и был вопрос об этом. Получается, что в отличии от API1, где каждая метка - это отдельный объект, который не требует специальной индексации или нумерации, здесь создаваемый объект для ссылки требует ещё что-то.

Всё получилось - большое спасибо за уделённое мне время

 

 

Попробовал сделать неглобальной - (была глобальная, потому что в описании перехода на API2, в примерах она глобальная - я подумал, что это какое-то новшество) + надо объявить её локальной!:-)
Собственно, у меня и был вопрос об этом. Получается, что в отличии от API1, где каждая метка - это отдельный объект, который не требует специальной индексации или нумерации, здесь создаваемый объект для ссылки требует ещё что-то.

Нет, по сути объекты одни и теже javascript-объекты, разница лишь в том, что в 2.0 другая структура классов, другие названия методов и т.д.

А стиль вашей работы с ними зависит от Вас.

В примерах это (глобальные переменные) было сделано для простоты.

Часто люди пишут подобное:

открыть чтото на карте

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

Глобальные переменные это безусловно зло и нужно научиться обходиться без них. В реальном проекте, конечно же.

 

 

Всё получилось - большое спасибо за уделённое мне время

Пожалуйста, рекомендую всё же прочесть хорошую книжку по javascript,

например, Девида Флэнагана, можно найти и на торрентах бесплатно.

 

 

 

Вынужден опять вернуться, т.к. всё-таки некорректно работает. В том примере
http://biopointcosmetics.ru/page/gde
если два раза кликнуть(не двойной) в меню города, то баллун магазина при клике по меню магазина не открывается
консоль выдаёт ошибку

Ошибка: TypeError: this._i is null
Источник: http://api-maps.yandex.ru/2.0.25/release/combine.xml?modules=gcf8oWgkgwgnghkUkSkTgrkZglgfgmnSgHnXoanVgLgqgegigvgulLgplPjPkNkynQkEkDf9ktgYg2lOedlMd5eKfRgbhbd1eOkHkFkIkKkLkJg1oieqfHm4m3fIfMjZfLnbm6m5m7nam8hthuhqhrnDnwnznpntfOhkelnRo1o3o2o6o5oZoXoYd6eelSlDlFeSeVeTeRf2kmdYegehdZepd4eJd9gGd2enekeiejemfkfjfffufxe7lwlvltlslqlplllulnlrlkgjlRk0kXfgfeggfdkWgokVnTh7gMgFfhgKlTfPobfEfFfyeZe2k8jTf4eQe6lQeclzlAlxlyhnjBjvjMoGoHjSkQkAkuhCgdeUf6jmjkhli0jpfmhDfGhhj1hAfBfwkgiEfQlBf7f5khkki1kfg0fng7g9eojYlNjVf3efjWjUfvfpjujyjxjXfKi5m9jzjRjaoQoPfrmGhvlVjshsnEo8nBnqnuhQhPhShRkvhapKkonhhmhdhfhehilUlJlGlCd8lEhjiWjti7fiePklhohpeafXfYnAgOgJn9fseLf1kdfziDgEn7lmlog6g3kYmMjle5mFmEnWidjfhBe1iJiRk7d3g8nrjrjqjFoImWoFmZi3jKeXoqiXmxoVhgjNerhXeshWhVhUfcjnfZjOjQe9gakwkikjkefoebfNm0m2jDmTi8jJmImBnGo7nCpopIpJpppnoLlZhKhJhNhLn3f0n5hcollHi9iVe3iHn2g4lImOmKmHmCjglWeWjdiPhYeui6fqjIjGmVmYj2hzeHo0oUiNjHjAmSmXjCjwmUe8lKfJfCiZmQmPcAc3cRaOb9pCp3pfpbpzpypxpco9pDpepdpaddcVdKbApjoJeYlYhMflftgDe4jij6jcjbh4o4iLe0jLjEm1mRdbdzcTbbcSc5axcQcPakaibYc6c9pBpEaycObNdEdxdHbwpwbcaRbTaZj0jjondrc7bJbmdVcCaBdkdlaScBaocKb3bdaEcbatbRaab4dPa7bGdnaUp2pAcWacbia3aTbxdodIdvagbBahcsdWc8cYdBbacecqcN&jsonp_prefix=ymaps2_0_25
Строка: 1
Аналогично, если просто переключить магазины туда-сюда
Кстати, если переменная глобальная, то этой ошибки нет

У меня падает на создании карты.

Потому что Вы создаете ее не дожидаясь готовности АПИ.

function Do_Map() {var myMap = new ymaps.Map ("YMaps_all", {Uncaught TypeError: undefined is not a functioncenter: [citi[thisciti]['lat'], citi[thisciti]['long']],zoom: citi[thisciti]['zoom'],type: "yandex#map"});