单击视图时出现 Appcelerator 范围问题
Appcelerator scope issue when clicking a view
我快要发疯了,想弄清楚为什么我的变量的作用域无法从我的 Appcelerator 项目中的数据库的 60 项循环中选取正确的值。
我的地图标记显示了正确的标签,但是当我单击它时,无论我尝试哪种范围界定组合,我都无法在警报中获得正确的值。每次都是returns第60条。
可能是小学生的错误,但这让我抓狂。
这是我的功能
function loadAnimals() {
var db = Ti.Database.open('myDB');
var getSpecies = db.execute('select * from species');
while (getSpecies.isValidRow()) {
var speciesID = getSpecies.fieldByName('speciesnid');
var speciesName = getSpecies.fieldByName('speciesname');
var speciesDesc = getSpecies.fieldByName('speciesdescription');
var speciesLatitude = getSpecies.fieldByName('specieslatitude');
var speciesLongitude = getSpecies.fieldByName('specieslongitude');
var speciesConStatus = getSpecies.fieldByName('speciesconservationstatus');
var speciesMarkerFilename = getSpecies.fieldByName('speciesiconfilename');
var speciesMarkerIcon = getSpecies.fieldByName('speciesmapicon');
var speciesMarkerURI = getSpecies.fieldByName('speciesmapiconurl');
var speciesImageFullPath = speciesMarkerURI.replace("public://", "http://myurl.com/");
var speciesImageFullPath = speciesImageFullPath.replace(" ", "%20");
var imageFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerIcon);
var iconFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerFilename);
var annotationView = Ti.UI.createView({
backgroundColor: '#222222',
width: 150,
height: 75,
layout:'vertical'
});
var addtoTourView = Ti.UI.createView({
height:20,
backgroundColor:'#6ea108'
});
var addtoTourTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'ADD TO TOUR',
width: 150,
height: 15,
top:3,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'bold'
}
});
var annotationTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'test',
width: 150,
height:15,
top:0,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'normal'
}
});
var blankView = Ti.UI.createView({
backgroundColor: '#222222',
width: 1,
height: 73,
borderRadius: 0
});
annotationView.add(addtoTourView);
addtoTourView.add(addtoTourTitle);
annotationView.add(annotationTitle);
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID,
rightView: annotationView,
leftView: blankView
}));
addtoTourView.addEventListener('click', function(e) {
//alert(speciesName + ' has dded to Tour');
var dialog = Ti.UI.createAlertDialog({
message: 'Added to your Tour',
ok: 'Continue',
title: speciesName //this is the 60th entry, not the correct one
});
dialog.show();
// do the insert into the DB
var db = Ti.Database.open('myDB');
db.execute('INSERT INTO tour (speciesnid) VALUES (?)', speciesID); // same with this ID, needs to the correct ID
db.close();
});
annotationTitle.text = speciesName;
//load up the next record
getSpecies.next();
};
// close the database
getSpecies.close();
// add markers to map
mapview.annotations = annotations;
};// loadAnimals 函数结束
谁能指出我做错了什么?
在创建要添加到地图的注释数组时,将您的标题添加到注释参数以及您使用键设置的物种 ID - myid。
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID, // We'll be querying this
myname: speciesName, // and also this
rightView: annotationView,
leftView: blankView
}));
然后将您的事件侦听器添加到地图上一次 object 而不是每个单独的注释 object。这样可以更有效地管理内存,是添加内存的正确方法。不要为每个注释添加事件侦听器,这是不好的做法。
// Handle click events on any annotations on this map.
mapview.addEventListener('click', function(evt) {
Ti.API.info("speciesID " + evt.annotation.myid + " clicked, speciesName: " + evt.annotation.myname);
});
在这个单一的事件侦听器上,您现在可以通过检查
访问每个注释的单独属性来创建警报对话框和数据库插入
evt.annotation
在地图上 object 您还可以执行以下操作:
click
事件包含一个您可以查询的值 clicksource
此 clicksource 将让您知道来源 - pin, annotation, leftButton, rightButton, leftView, rightView, title, or subtitle
您可以在事件侦听器中使用它。
触发事件的来源 object - source
也可用。然后,您可以测试 clicksource 是否不为 null 以及源是否来自要放置触发器的 "ADD TO TOUR" 元素。仍然从 evt.annotation
获取所有注释属性
Michael 的解决方案听起来不错。
让我 post 无论如何我要说什么。我专注于解释范围问题,解释为什么您的代码没有达到您的预期。
在 javascript 中,范围绑定到函数。当您在循环 (for/while/do...) 中声明一个变量时,事情会变得有点混乱。您不是在创建新变量,您只是用该名称覆盖第一个(也是唯一一个)变量的值。
因此,您在函数 loadAnimals 中有 1 个变量,称为 speciesName。在 while 循环中,您只需覆盖该变量的值。在第 60 次迭代之后,变量只记住您最后设置的内容。
当客户端点击标记时,循环结束,这个值早就设置好了。
注意:您的地图服务可能提供了解决方案,但我不知道。
- 1个解决方案:'this'.
'this' 变量告诉您受影响的内容。在 onClick 回调中,这是被点击的元素。
您的问题的解决方案可能涉及 'this'。但我不确定具体如何。
这是我的意思的一个例子。
<h2>Click on the animal</h2>
<p>dog</p>
<p>cat</p>
<p>hamster</p>
<script>
function loadAnimals() {
var speciesName = '';
var animalElements = document.getElementsByTagName('p');
for (var i=0; i<animalElements.length; i++) {
speciesName = animalElements[i].innerHTML ; // notice, this variable will be overridden, so this variable is useless within the onClick callback.
animalElements[i].addEventListener('click', function(e) {
// variable 'this' is the <p> that was clicked on.
var value_clicked_on = this.innerHTML;
alert(value_clicked_on);
});
}
}
window.onload = loadAnimals;
</script>
我快要发疯了,想弄清楚为什么我的变量的作用域无法从我的 Appcelerator 项目中的数据库的 60 项循环中选取正确的值。
我的地图标记显示了正确的标签,但是当我单击它时,无论我尝试哪种范围界定组合,我都无法在警报中获得正确的值。每次都是returns第60条。
可能是小学生的错误,但这让我抓狂。
这是我的功能
function loadAnimals() {
var db = Ti.Database.open('myDB');
var getSpecies = db.execute('select * from species');
while (getSpecies.isValidRow()) {
var speciesID = getSpecies.fieldByName('speciesnid');
var speciesName = getSpecies.fieldByName('speciesname');
var speciesDesc = getSpecies.fieldByName('speciesdescription');
var speciesLatitude = getSpecies.fieldByName('specieslatitude');
var speciesLongitude = getSpecies.fieldByName('specieslongitude');
var speciesConStatus = getSpecies.fieldByName('speciesconservationstatus');
var speciesMarkerFilename = getSpecies.fieldByName('speciesiconfilename');
var speciesMarkerIcon = getSpecies.fieldByName('speciesmapicon');
var speciesMarkerURI = getSpecies.fieldByName('speciesmapiconurl');
var speciesImageFullPath = speciesMarkerURI.replace("public://", "http://myurl.com/");
var speciesImageFullPath = speciesImageFullPath.replace(" ", "%20");
var imageFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerIcon);
var iconFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerFilename);
var annotationView = Ti.UI.createView({
backgroundColor: '#222222',
width: 150,
height: 75,
layout:'vertical'
});
var addtoTourView = Ti.UI.createView({
height:20,
backgroundColor:'#6ea108'
});
var addtoTourTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'ADD TO TOUR',
width: 150,
height: 15,
top:3,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'bold'
}
});
var annotationTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'test',
width: 150,
height:15,
top:0,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'normal'
}
});
var blankView = Ti.UI.createView({
backgroundColor: '#222222',
width: 1,
height: 73,
borderRadius: 0
});
annotationView.add(addtoTourView);
addtoTourView.add(addtoTourTitle);
annotationView.add(annotationTitle);
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID,
rightView: annotationView,
leftView: blankView
}));
addtoTourView.addEventListener('click', function(e) {
//alert(speciesName + ' has dded to Tour');
var dialog = Ti.UI.createAlertDialog({
message: 'Added to your Tour',
ok: 'Continue',
title: speciesName //this is the 60th entry, not the correct one
});
dialog.show();
// do the insert into the DB
var db = Ti.Database.open('myDB');
db.execute('INSERT INTO tour (speciesnid) VALUES (?)', speciesID); // same with this ID, needs to the correct ID
db.close();
});
annotationTitle.text = speciesName;
//load up the next record
getSpecies.next();
};
// close the database
getSpecies.close();
// add markers to map
mapview.annotations = annotations;
};// loadAnimals 函数结束
谁能指出我做错了什么?
在创建要添加到地图的注释数组时,将您的标题添加到注释参数以及您使用键设置的物种 ID - myid。
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID, // We'll be querying this
myname: speciesName, // and also this
rightView: annotationView,
leftView: blankView
}));
然后将您的事件侦听器添加到地图上一次 object 而不是每个单独的注释 object。这样可以更有效地管理内存,是添加内存的正确方法。不要为每个注释添加事件侦听器,这是不好的做法。
// Handle click events on any annotations on this map.
mapview.addEventListener('click', function(evt) {
Ti.API.info("speciesID " + evt.annotation.myid + " clicked, speciesName: " + evt.annotation.myname);
});
在这个单一的事件侦听器上,您现在可以通过检查
访问每个注释的单独属性来创建警报对话框和数据库插入evt.annotation
在地图上 object 您还可以执行以下操作:
click
事件包含一个您可以查询的值 clicksource
此 clicksource 将让您知道来源 - pin, annotation, leftButton, rightButton, leftView, rightView, title, or subtitle
您可以在事件侦听器中使用它。
触发事件的来源 object - source
也可用。然后,您可以测试 clicksource 是否不为 null 以及源是否来自要放置触发器的 "ADD TO TOUR" 元素。仍然从 evt.annotation
Michael 的解决方案听起来不错。
让我 post 无论如何我要说什么。我专注于解释范围问题,解释为什么您的代码没有达到您的预期。
在 javascript 中,范围绑定到函数。当您在循环 (for/while/do...) 中声明一个变量时,事情会变得有点混乱。您不是在创建新变量,您只是用该名称覆盖第一个(也是唯一一个)变量的值。
因此,您在函数 loadAnimals 中有 1 个变量,称为 speciesName。在 while 循环中,您只需覆盖该变量的值。在第 60 次迭代之后,变量只记住您最后设置的内容。
当客户端点击标记时,循环结束,这个值早就设置好了。
注意:您的地图服务可能提供了解决方案,但我不知道。
- 1个解决方案:'this'.
'this' 变量告诉您受影响的内容。在 onClick 回调中,这是被点击的元素。
您的问题的解决方案可能涉及 'this'。但我不确定具体如何。
这是我的意思的一个例子。
<h2>Click on the animal</h2>
<p>dog</p>
<p>cat</p>
<p>hamster</p>
<script>
function loadAnimals() {
var speciesName = '';
var animalElements = document.getElementsByTagName('p');
for (var i=0; i<animalElements.length; i++) {
speciesName = animalElements[i].innerHTML ; // notice, this variable will be overridden, so this variable is useless within the onClick callback.
animalElements[i].addEventListener('click', function(e) {
// variable 'this' is the <p> that was clicked on.
var value_clicked_on = this.innerHTML;
alert(value_clicked_on);
});
}
}
window.onload = loadAnimals;
</script>