2011-08-22 149 views
0

我为地图创建了一个标记列表,当它们被拖动到地图上时(通过jQuery可拖动) - 图像被替换为地图标记。Javascript可变范围问题

我遇到的问题是,当创建我的标记控制器 - 它们都有一个特定的类型 - 从列表中提取。当我遍历列表时,每个可拖动元素都会得到它的'stop'函数,该函数使用变量'type'...现在,当每个元素被拖曳时 - 它们的行为就好像它们是最后一个'类型'一样元素,而不是他们自己的。

任何人都可以建议我如何重组,以便每个标记保持其特定类型?

var createMarkerControl = function(){  
    var markerTypes = ['custom', 'exit', 'food', 'medical', 'shelter', 'video']; 
    var control = document.createElement('div'); 
    control.setAttribute('id', 'markerInput'); 

    for (var i = 0; i < markerTypes.length; i++){ 
     var image = document.createElement('img'); 
     image.setAttribute('id', 'draggable-' + markerTypes[i]); 
     image.setAttribute('src', 'images/gui/' + markerTypes[i] + '.png'); 
     image.style.width = '30px'; 

     //Set type 
     var type = markerTypes[i]; 

     //Make elements dragable/dropable     
     control.appendChild(image); 

     $(image).draggable({ 
      helper: 'clone', 
      stop: function(e){ 
      //Add marker to map 
      var point = new google.maps.Point(e.pageX, e.pageY); 
      customMap.addPlacemark(point, type); 
      }, 
      cursorAt: {left: 15, top: 0} 
     }); 


    } 

    map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(control); 
} 
+1

你不应该使用'var'声明中的'for'循环内,仅供参考。 – AlienWebguy

回答

3

这是因为JavaScript没有块级作用域,只有函数级作用域。 imagetype变量的作用域为createMarkerControl,而不是循环。更重要的是,它们的范围是外部的可拖动关闭,因此每个关闭将共享type变量。

我想你想你的内环看起来更像这样:

var createMarkerControl = function(){  
    var markerTypes = ['custom', 'exit', 'food', 'medical', 'shelter', 'video']; 
    var control = document.createElement('div'); 
    control.setAttribute('id', 'markerInput'); 

    var createDraggable = function(image, type) { 
     image.setAttribute('id', 'draggable-' + type); 
     image.setAttribute('src', 'images/gui/' + type + '.png'); 
     image.style.width = '30px'; 

     //Make elements dragable/dropable     
     control.appendChild(image); 

     $(image).draggable({ 
      helper: 'clone', 
      stop: function(e){ 
      //Add marker to map 
      var point = new google.maps.Point(e.pageX, e.pageY); 
      customMap.addPlacemark(point, type); 
      }, 
      cursorAt: {left: 15, top: 0} 
     }); 
    }; 

    for (var i = 0; i < markerTypes.length; i++){ 
     var image = document.createElement('img'); 

     //Set type 
     var type = markerTypes[i]; 

     createDraggable(image, type); 

    } 

    map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(control); 
} 

通过将逻辑的子功能,可以确保以typeimage引用是唯一的内部封闭。

+0

+1,但我会用直接属性访问替换对setAttribute的调用:例如'image.id ='draggable-'+ markerTypes [i];'因为它更快,更不容易出错(输入更少)。 – RobG

+0

啊,非常聪明。考虑这个教训。谢谢! – Tim

+0

@RobG - 已经修复!我错过了我的复制和粘贴。 :-) – OverZealous

2

我不认为在JavaScript中的for循环得到自己的变量范围(就像他们有时在其他语言中那样),所以您定义的type变量被绑定在函数的作用域中。所以你真的需要另一个坚实的范围。

我个人会做一个帮助函数,为你生成stop闭包。这将创造一个稳定的范围在您关闭可以住......事情是这样的:

var createMarkerControl = function(){  
    var markerTypes = ['custom', 'exit', 'food', 'medical', 'shelter', 'video']; 
    var control = document.createElement('div'); 
    control.setAttribute('id', 'markerInput'); 

    for (var i = 0; i < markerTypes.length; i++){ 
     var image = document.createElement('img'); 
     image.setAttribute('id', 'draggable-' + markerTypes[i]); 
     image.setAttribute('src', 'images/gui/' + markerTypes[i] + '.png'); 
     image.style.width = '30px'; 

     //Set type 
     var type = markerTypes[i]; 

     //Make elements dragable/dropable     
     control.appendChild(image); 

     $(image).draggable({ 
      helper: 'clone', 
      stop: createStopper(type), 
      cursorAt: {left: 15, top: 0} 
     }); 


    } 

    map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(control); 
} 


var createStopper = function(type) { 
    return function(e){ 
     var point = new google.maps.Point(e.pageX, e.pageY); 
     customMap.addPlacemark(point, type); 
    } 
} 
0

试试这个:

$(image).data('type',type).draggable({ 
     helper: 'clone', 
     stop: function(e){ 
     //Add marker to map 
     var point = new google.maps.Point(e.pageX, e.pageY); 
     customMap.addPlacemark(point, $(this).data('type')); 
     }, 
     cursorAt: {left: 15, top: 0} 
    }); 

在你的代码,type被覆盖在for循环每次迭代中,但在任何给定的迭代中,type的值都不会附加到可拖动的图像上,而只是在stop回调中引用它。当stop被触发时,type值就是上次分配的值。我上面提供的想法是简单地将type的值附加到对象,以便它可以在回调中从其本身引用它。

0

我知道已经发布了正确的答案,它们很好,但简单的(恕我直言)解决方案只是将您需要的代码包装在(function(){ ... })();中,因此它创建了一个新的范围。

var createMarkerControl = function(){  
    var markerTypes = ['custom', 'exit', 'food', 'medical', 'shelter', 'video']; 
    var control = document.createElement('div'); 
    control.setAttribute('id', 'markerInput'); 

    for (var i = 0; i < markerTypes.length; i++) 
    (function() { 
     var image = document.createElement('img'); 
     image.setAttribute('id', 'draggable-' + markerTypes[i]); 
     image.setAttribute('src', 'images/gui/' + markerTypes[i] + '.png'); 
     image.style.width = '30px'; 

     //Set type 
     var type = markerTypes[i]; 

     //Make elements dragable/dropable     
     control.appendChild(image); 

     $(image).draggable({ 
      helper: 'clone', 
      stop: function(e){ 
      //Add marker to map 
      var point = new google.maps.Point(e.pageX, e.pageY); 
      customMap.addPlacemark(point, type); 
      }, 
      cursorAt: {left: 15, top: 0} 
     }); 


    })(); 

    map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(control); 
} 

http://jsfiddle.net/xXkcG/2/