Клуб API Карт

TypeError: this._icons[this._type] is undefined

nikita.pimoshenko
13 декабря 2012, 16:30

Ситуация такова, есть карта дилеров по России, после добавления новых элементов карта стала работать некорректно - а именно сместились метки, не открываются балуны. Причем это связано с добавлеием кокретных элементов, на вид элеметы ичем не отличаются от прочих, в мод дебаге скрипта увидел вот, что

TypeError: this._icons[this._type] is undefined собтсвенно вопрос - возможно вы подскажете мне аправлеие в котором копать?

Вот собственно сам код:
 
function YaMaps()
{
  this.data           = { markers         : {},
                          dealers         : {},
                          cluster_markers : []
                        };
  this.map            = {};
  this.MrkImgSize     = [102,37];              //Размер флажка метки в пикселях
  this.MrkImgOffset   = [-14, -37];             //Положение точки устаова флажка метки считается от верхнего левого угла изображения
  this.MrkImgHref     = "/f/marker_icon.png";  //Путь к иконке флажка метки
  this.myCluster      = {};
  this.myClusterIcons = [];
}
//----------------Создаем карту--------------------------------------------------------------------------------------------------//
YaMaps.prototype.create = function(map_canvas, markers, dealers, zoom)
{
  this.data.markers = markers;
  this.data.dealers = dealers;
  var zoom_zoom = zoom;
  var myMap = new ymaps.Map(map_canvas,{
              center: [61.658998,78.331185],
              zoom: zoom_zoom,
              type: 'yandex#map',
          }, {
              balloonPane: 'movableOuters',            //перемещаем слой Балуна в movableOuters вместе с его тенью
              balloonShadowPane: 'movableOuters',      //это позволяет отображать его за границами карты, т.е. он не режется ее границами
          });
  this.init_marks(true);
  myMap.geoObjects.add(this.myCluster);
  var mapSize = myMap.container.getSize();
  myMap.balloon.events
                // При открытии балуна начинаем слушать изменение центра карты
                .add('open', function (e) {
                    var balloon = e.get('balloon'),
                        isDisplaced = false;

                    eventsGroup = myMap.events.group().add('actiontick', function (e) {
                        var tick = e.get('tick'),
                            mapBounds = [
                                [tick.globalPixelCenter[0] - mapSize[0] / 2, tick.globalPixelCenter[1] - mapSize[1] / 2],
                                [tick.globalPixelCenter[0] + mapSize[0] / 2, tick.globalPixelCenter[1] + mapSize[1] / 2]
                            ],
                            balloonPosition = balloon.getPosition(),
                            zoomFactor = Math.pow(2, tick.zoom - myMap.getZoom()),
                            isVisible = isPointInBounds(mapBounds, zoomFactor == 1 ? balloonPosition : [
                                balloonPosition[0] * zoomFactor,
                                balloonPosition[1] * zoomFactor
                            ]);

                        // Проверяем, находится ли балун в видимой области
                        if (!isVisible && !isDisplaced) {
                            // Если геоточка уже вне видимой области, переносим балун в обычный контейнер.
                            balloon.options.set({
                                pane: 'overlays',
                                shadowPane: 'shadows'
                            });
                            isDisplaced = true;
                        } else if (isVisible && isDisplaced) {
                            // Иначе - возвращаем его в movableOuters.
                            balloon.options.set({
                                pane: 'movableOuters',
                                shadowPane: 'movableOuters'
                            });
                            isDisplaced = false;
                        }
                    });
                })
                // При закрытии балуна удаляем слушатели
                .add('close', function () {
                    eventsGroup.removeAll();
                });

            //myPlacemark.balloon.open();

        function isPointInBounds (mbr, point) {
            return point[0] >= mbr[0][0] && point[0] <= mbr[1][0] && point[1] >= mbr[0][1] && point[1] <= mbr[1][1];
        }   
        myMap.controls
                // Кнопка изменения масштаба
                .add('zoomControl')
                // Список типов карты
                .add('typeSelector')
                // Стандартные инструменты карты
                .add('mapTools'); 
        this.map = myMap;
}
//---------------Инициализируем метки и помещаем их в кластер-------------------------------------------------------------------------//
YaMaps.prototype.init_marks = function(clusterize)
{
  for(var i in this.data.markers){
    if(this.data.markers[i].coordinates != '') {
      var marker    = this.build_marks(this.data.markers[i]);
      marker.dealer = this.data.markers[i].dealer;
      marker.filial = this.data.markers[i].filial;
      this.data.cluster_markers.push(marker);
    }
    else
    {
      this.CoordUpdate(this.data.markers[i]);
    }
  }
  if(clusterize)
  {
    MyIconContentLayout = ymaps.templateLayoutFactory.createClass('<em style="display: none">$[properties.geoObjects.length]</em>');
    this.myClusterIcons = [{
          href   : this.MrkImgHref,
          size   : this.MrkImgSize,
          offset : this.MrkImgOffset
        }]
    this.myCluster = new ymaps.Clusterer({ clusterIcons             : this.myClusterIcons,
                                           clusterDisableClickZoom  : true,
                                           clusterIconContentLayout : MyIconContentLayout });
    this.myCluster.options.set({
      gridSize: 60
    })
    this.myCluster.add(this.data.cluster_markers);
  }
}
//---------------Создаем метки--------------------------------------------------------------------------------------------------------//
YaMaps.prototype.build_marks = function(data)
{
 
  var myGeoObjects = {};
  myGeoObjects = new ymaps.GeoObject({
    geometry: {
      type                : "Point",
      coordinates         : this.StringToCoord(data.coordinates)
    },
    properties: {
      clusterCaption      : this.data.dealers[data.dealer].company,
      balloonContentBody  : this.create_content(this.data.dealers[data.dealer],data.filial)
    }}, {
    iconImageHref         : this.MrkImgHref,
    iconImageSize         : this.MrkImgSize,
    iconImageOffset       : this.MrkImgOffset,
    hideIconOnBalloonOpen : false
  });
  console.log(myGeoObjects);
  return myGeoObjects;
}
//---------------Переводим строковые данные в массив чисел, который принимает конструктор класса Placemark--------------------------//
YaMaps.prototype.StringToCoord = function(coords)
{
  if(typeof(coords) === 'string')
  {
    coords = coords.split(',');
    return coords;
  }
  else
  return coords;
}
//---------------Строим содержимое Балуна (Popup с информацией о филиалах)----------------------------------------------------------//
YaMaps.prototype.create_content = function(dealer,filial)
{
  var d  = '<div class="text_container" style="min-width: 300px; max-width: 500px;">';
  if( dealer.logo )
  {
    d += '<img width="100" alt="" class="left" src="' + dealer.logo + '"></a>';
  }
  d += '<div class="nofloat"><div class="s14 bb m10 black"><a href="/dealers/'+dealer.id+'">'+dealer.company+'</a></div>';
  d += ((dealer.url!='')?'<div class="s11 black"><span class="bb">URL-адрес:</span>&nbsp;<a href="'+dealer.url+'" target="_blank">'+dealer.url+'</a></div>':'');
  if( dealer.filials[filial].address )
  {
    d += '<div class="s11"><span class="bb">Адрес:</span>&nbsp;'+dealer.filials[filial].address+'</div>';
  }
  if( dealer.filials[filial].phone )
  {
    d += '<div class="s11"><span class="bb">Тел:</span>&nbsp;'+dealer.filials[filial].phone+'</div>';
  }
  d += '<br></div></div>';
  var myBalloonLayout = ymaps.templateLayoutFactory.createClass(d);
  ymaps.layout.storage.add('my#intensorlayout', myBalloonLayout);
  return d;
}
//------------------Перехватываем клик на города представителей---------------------------------------------------------------------//
YaMaps.prototype.cities = function(class_name)
{
  var self = this;
  $('.'+class_name).click(function(){
    var city = $(this).attr('id').match(/\w+-([\-А-я]+)/)[1];
    self.create_baloon_section(city, 'city');
  });
}
//------------------Ищем адреса для внутренней страницы диллера--------------------------------------------------------------------//
YaMaps.prototype.address = function(class_name)
{
  var self = this;
  $('.'+class_name).click(function(){
    var addr = $(this).attr('id');
    self.create_baloon_section(addr, 'address');
  });
}
//------------------Открываем балун для адреса\города------------------------------------------------------------------------------//
YaMaps.prototype.create_baloon_section = function(addr, section)
{
  var self = this;
  var mark;
  for(var i in this.data.dealers)
  {
    if( this.data.dealers[i].filials && this.data.dealers[i].filials.length )
    {
      for(var j = 0; j < this.data.dealers[i].filials.length; j++)
      {
        if( this.data.dealers[i].filials[j][section].find(addr) )
        {
          this.create_content(this.data.dealers[i], j);
          if( !mark )
          {
            for(var k in this.data.markers)
            {
              if( this.data.cluster_markers[k].dealer == i && this.data.cluster_markers[k].filial == j )
              {
                mark = this.data.cluster_markers[k];
                break;
              }
            }
          }
        }
      }
    }
  }
   if(mark)
  {
     if(this.map.balloon.isOpen())
      this.map.balloon.close();
    var Point = mark.geometry.getCoordinates();
    this.map.setCenter(Point);
    window.scrollBy(0, -9999);
    var geoObjectState = this.myCluster.getObjectState(mark);
    if(geoObjectState.isShown)
    {
     
      if(geoObjectState.isClustered)
      {
       
        setTimeout( function() { geoObjectState.cluster.balloon.open(); }, 40);
      }
      else
      {
        setTimeout( function() { mark.balloon.open(); }, 40);
      }
    }
  }
}
//------------------Регистрация новых дилеров со страницы сайта-------------------------------------------------------------------//
YaMaps.prototype.regDealer = function(form, add_group_action)
{
  var index_group = 0;
  var self        = this;
  this.form       = form;
  this.regData    = {};
  this.regMaps    = {};
  this.regMarks   = {};
  $(document).on("blur", '.form-filials-city, .form-filials-address', function(){
    if( $(this).val().length )
    {
      var id = $(this).attr('id');
      id = id.match(/form-filials-\w+-?(\d)*/)[1] || 0;
      self.showAddr($(this), id);
    }
  });
  $('#add_filials').live('click',function(e){
    e.preventDefault();
    index_group++;
    add_group_action('form-filials');
    $($('.form-filials-map')[index_group]).hide().html('');
  });
}
//------------------Добавляем нвоые филаилы в массив адресов дял показа-------------------------------------------------------------//
YaMaps.prototype.showAddr = function(e, id)
{
  var self      = this;
  var type      = $(e).attr('id').match(/form-filials-(\w+)/)[1];
  var loc_name  = $(e).val();
 
  $.mouseLoader(true);
 
  if( type.match(/address/) && this.form.filials[id] && loc_name.indexOf(this.form.filials[id].city) === -1 )
  {
    loc_name = this.form.filials[id].address = translate.c+' '+this.form.filials[id].city +', '+loc_name;
    $($('.form-filials-address')[id]).attr('value', loc_name);
  }
  ymaps.geocode(loc_name, { results: 1 }).then(function (res){
    var location = res.geoObjects.get(0).geometry.getCoordinates();
    self.regShowMark( location , type === 'address' ? 15 : null, id);
    self.regData[id] = { 'name' : loc_name, 'coordinates' : location.join(',') };
   
    e.removeClass('input_error');
      if( id === 0 )
      {
        submit_obstacle.town = false;
      }
      $($('.form-filials-city-wrong')[id]).hide();
    },
    function(err)
    {
      e.addClass('input_error');
      if( id === 0 )
      {
        submit_obstacle.town = "укажите город";
      }
      $($('.form-filials-city-wrong')[id]).show();
    });
   
  $.mouseLoader(false);
}
//------------------Покажем новые филиалы на карте---------------------------------------------------------------------------------//
YaMaps.prototype.regShowMark = function(location, zoom, num)
{
  var self = this;
  if( $('.form-filials-map')[num].style.display === 'none' )
  {
    console.log($('.form-filials-map')[num]);
    $($('.form-filials-map')[num]).show();
    this.regMaps[num] = new ymaps.Map($('.form-filials-map')[num],{
              center: location,
              zoom: zoom || 4,
              type: 'yandex#map',
          });
    this.regMaps[num].controls
                // Кнопка изменения масштаба
                .add('smallZoomControl')
                // Стандартные инструменты карты
                .add('mapTools');
   
  }
  if(zoom)
  this.regMaps[num].setZoom(zoom);
  this.regMaps[num].setCenter(location);
  if( this.regMarks[num] )
  {
    this.regMaps[num].geoObjects.remove(this.regMarks[num]);
    delete this.regMarks[num];
  }
  this.regMarks[num] = new ymaps.GeoObject({
    geometry: {
      type               : "Point",
      coordinates        : location
    }},
  {
    draggable            : true,
    iconImageHref        : this.MrkImgHref,
    iconImageSize        : this.MrkImgSize,
    iconImageOffset      : this.MrkImgOffset
  });
  this.regMaps[num].geoObjects.add(this.regMarks[num]);
  this.regMarks[num].events.add("dragend", function(e){
    self.regData[num].coordinates = e.get('target').geometry.getCoordinates().join(',');
  });
}
//------------------Добавление координат в базу------------------------------------------------------------------------------------//
YaMaps.prototype.RegUpdCoord = function()
{
  console.log(this_url);
  var coords = $.obj.parse(this.regData);
  $.post(this_url, 'action=add_coords&coordinates=' + encodeURIComponent(coords), null, 'json');
}
//------------------Обновляем координаты для элементов базы, у которых отсутствуют координаты--------------------------------------//
YaMaps.prototype.CoordUpdate = function(marker)
{
  var temp;
  var self = this;
  ymaps.geocode(marker.address, { results: 1 }).then(function (res){
    var coord = { 'name'             : marker.address,
                  'coordinates'      : res.geoObjects.get(0).geometry.getCoordinates().join(',') };
    var send = $.obj.parse(coord);
    $.post(this_url, 'action=address_update&compiled=1&data=' + encodeURIComponent(send), null, 'json');
    })
}
 

 

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

Опять же интересная история - включаю/выключаю грид сайз, и некоторые элементы ранее не отображавшиеся появляются.Что то связанное с кластерами тут. Ругается что не может взять размер от undefined. Я прекрасно понимаю, что я тоже бы е взял, о вроде все объекты передавамые скрипту дефайнед.

Код, если честно, ниасилила =) Но по симптомам похоже, что у вас некорректно задаются опции clusterIcons и clusterNumbers. Количество элементов в массиве clusterIcons должно быть на 1 больше, чем количество элементво в clusterNumbers. 

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

эмм а какова последняя версия апи на данный момент?)

И если не трудно не могли бы вы описать как создать кластериконок на 1 больше, чем количество кластеров? Т.к. сейчас я попробовал подключить 2.0.21 версию, проблема осталась.

Да, с версией я вас обманула - правки сделаны, но выедут только в будущих релизах.

У вас задается только 1 иконка для кластеров, передайте в таком случае в опцию clusterNumbers пустой массив. Должно заработать.