2011-08-22 116 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/