Given this code:
var Container = CRM.GetBlock("Container");
var CustomCommunicationDetailBox = CRM.GetBlock("CustomCommunicationDetailBox");
Container.AddBlock(CustomCommunicationDetailBox);
if(!Defined(Request.Form)){
CRM.Mode=Edit;
}else{
CRM.Mode=Save;
}
CRM.AddContent(Container.Execute());
var sHTML=CRM.GetPageNoFrameset();
Response.Write(sHTML);
Im calling this .asp page with this parameters but does not seems to work
popupscreeens.asp?SID=33185868154102&Key0=1&Key1=68&Key2=82&J=syncromurano%2Ftabs%2FCompany%2FCalendarioCitas%2Fcalendariocitas.asp&T=Company&Capt=Calendario%2Bcitas&CLk=T&PopupWin=Y&Key6=1443Act=512
Note the Key6=Comm_Id and Act=512??? which i believe it is when editing?
How can i achieve to fill the screen's field with entity dada?
In this case it is a communication entity
In order to populate a custom screen with data, you need to pass the data to the screen.
First, you need to get the Id value. In this case, we're getting it from the URL:
var CommId = Request.QueryString("Key6") + '';
We're going to put a few other checks in though. These are mainly to handle scenarios that have come up in different versions or from different user actions.
// check we have a value and get the Id from context if we don't
if(CommId == 'undefined'){
CommId = CRM.GetContextInfo("Communication","comm_communicationid");
}
// if CommId is still undefined, set it to zero to check later
// otherwise, make sure the URL only contains one CommId
if(CommId == 'undefined'){
CommId = 0;
} else if(CommId.indexOf(",") > -1){
CommId = CommId.substr(0,CommId.indexOf(","));
}
Certain user actions can make the URL hold multiple Ids in the same attribute. In these cases, those Ids are separated by commas. So, if the Id is not defined, we check if there is a comma in it. If there is, we take the 1st Id.
After we have the Id, we need to load the record. At this point, you should have already checked you have a valid id (E.g. not zero) and put some error handling in. In some pages you may want to display an error, in others you may want to create a new, blank record. This gets the record:
var CommRecord = CRM.FindRecord("communication","comm_communicationid = " + CommId);
After that, you need to apply the record to the screen. Using your example above:
CustomCommunicationDetailBox.ArgObj = CommRecord;
Adding all that to your script, you get:
var CommId = Request.QueryString("Key6") + '';
// check we have a value and get the Id from context if we don't
if(CommId == 'undefined'){
CommId = CRM.GetContextInfo("Communication","comm_communicationid");
}
// if CommId is still undefined, set it to zero to check later
// otherwise, make sure the URL only contains one CommId
if(CommId == 'undefined'){
CommId = 0;
} else if(CommId.indexOf(",") > -1){
CommId = CommId.substr(0,CommId.indexOf(","));
}
// add some error checking here
// get the communication record
var CommRecord = CRM.FindRecord("communication","comm_communicationid = " + CommId);
// get the container and the detail box
var Container = CRM.GetBlock("Container");
var CustomCommunicationDetailBox = CRM.GetBlock("CustomCommunicationDetailBox");
// apply the communication record to the detail box
CustomCommunicationDetailBox.ArgObj = CommRecord;
// add the box to the container
Container.AddBlock(CustomCommunicationDetailBox);
// set the moder
if(!Defined(Request.Form)){
CRM.Mode=Edit;
} else {
CRM.Mode=Save;
}
// output
CRM.AddContent(Container.Execute());
var sHTML=CRM.GetPageNoFrameset();
Response.Write(sHTML);
However, we would advise putting in more error/exception handling. If the user is saving the record, you will also need to add a redirect in after the page is written.
Six Ticks Support
Related
I am unable to maintain a session with a .aspx server. I am trying to scrape data by paginating, but it keeps telling me "The Results have expired. Please resubmit the search." I have tried maintaining cookies so I don't think that is the problem unless I somehow did it wrong?
I have to navigate through by first making a GET request to the following URL:
https://www.wandsworth.gov.uk/planning-and-building-control/search-planning-applications/
The following is the code I use to make the request.
First these are all my requires
const cheerio = require('cheerio');
const url = require('url');
const rp = require('request-promise');
const ss = require('string-similarity');
const tc = require('tough-cookie');
Here is how I make my request
var options = {
uri: 'https://www.wandsworth.gov.uk/planning-and-building-control/search-planning-applications/',
transform: function(body){ return cheerio.load(body) },
method: 'GET'
}
var $ = await rp(options);
Now I extract the information I need in order to make a successful post request, and I use the 'string-similarity' package to find a select element that closely matches a tag that matches my input.
// Extract selectable elements
var obj_collection = $('#cboStreetReferenceNumber')[0].children;
var collection = []; // array of inner strings for each select element
// Push innerHTML strings to collection
for(let i=0; i<obj_collection.length; i++){
try {
collection.push(obj_collection[i].children[0].data);
} catch(e) {
collection.push('');
}
}
// Find the best match for our given address
var matches = ss.findBestMatch(address, collection);
var cboStreetReferenceNumber=
obj_collection[matches.bestMatchIndex].attribs.value;
// These are used to verify us
var __VIEWSTATE = $('#__VIEWSTATE')[0].attribs.value;
var __VIEWSTATEGENERATOR = $('#__VIEWSTATEGENERATOR')[0].attribs.value;
var __EVENTVALIDATION = $('#__EVENTVALIDATION')[0].attribs.value;
var cboMonths = 1;
var cboDays = 1;
var csbtnSearch = 'Select';
var rbGroup = 'rbNotApplicable';
// Modify options
options.uri = $('#M3Form')[0].attribs.action;
options.method = 'POST';
options.form = {
cboStreetReferenceNumber,
__VIEWSTATE,
__VIEWSTATEGENERATOR,
__EVENTVALIDATION,
cboMonths,
cboDays,
csbtnSearch,
rbGroup
};
options.followAllRedirects = true;
options.resolveWithFullResponse = true;
delete options.transform;
Now with these options, I'm ready to make my request to page 1 of the data I'm looking for.
// method: #POST
// link: "Planning Explorer"
var body = await rp(options);
var $ = cheerio.load(body.body);
console.log(body.request);
var Referer = 'https://planning1.wandsworth.gov.uk' + body.req.path;
var scroll_uri = 'https://planning1.wandsworth.gov.uk/Northgate/PlanningExplorer/Generic/StdResults.aspx?PT=Planning%20Applications%20On-Line&PS=10&XMLLoc=/Northgate/PlanningExplorer/generic/XMLtemp/ekgjugae3ox3emjpzvjtq045/c6b04e65-fb83-474f-b6bb-2c9d4629c578.xml&FT=Planning%20Application%20Search%20Results&XSLTemplate=/Northgate/PlanningExplorer/SiteFiles/Skins/Wandsworth/xslt/PL/PLResults.xslt&p=10';
options.uri = scroll_uri;
delete options.form;
delete options.followAllRedirects;
delete options.resolveWithFullResponse;
options.method = 'GET';
options.headers = {};
options.headers.Referer = Referer;
options.transform = function(body){
return cheerio.load(body);
}
var $ = await rp(options);
Once I get the next page, I am given a table with 10 items and some pagination if there are more than 10 items available based on my POST request.
This all goes fine until I try to paginate to page 2. The resulting HTML body tells me that my search has expired and that I need to resubmit a search. That means going back to step 1 and submitting a POST request again, however that will always bring me to page 1 of the pagination.
Therefore, I need to somehow find a way to maintain a connection with this server while I 'scroll' through its pages.
I am using node.js & request-promise to make my requests.
The following is my code:
I have already tried maintaining cookies between requests.
Also, __VIEWSTATE shouldn't be the problem because the request to page 2 should be a GET request.
I was able to find a workaround by using the headless browser "Puppeteer" in order to maintain a connection with the server. However, I still do not know how to solve this problem by making raw requests.
I'm sure I'm doing something wrong... but every time I query on a calculated datasource, I get the error "cannot handle returning cyclic object."
Here's the gist:
I have a calculated model that fetches a user's google contacts and places the full name field into a table on the UI. The goal is to have a separate text box that can be used to search the full name field and then repopulate the table on the same page with the results of the search, similar to how google contacts search behavior works. The on value change event of the text box sends the textbox value to this server script:
function searchContacts (sq) {
var ds = app.models.Contacts.newQuery();
ds.filters.FullName._contains = sq;
var results = ds.run();
return results;
}
But every time I get the cyclic object error when the values are returned from that function. The error actually fires when the query run command (ds.run) is executed.
I've tried querying the datasource as well, but I've read somewhere that you can't query the datasource of a calculated model because it doesn't exist, so you have to query the model.
Any help would be much appreciated.
From your question it is not 100% clear, what you are trying to do. In case you are actually using Calculated Model, then your Server Script Query should look like this:
var sq = query.parameters.SearchQuery;
var contactsQuery = app.models.Contacts.newQuery();
contactsQuery.filters.FullName._contains = sq;
var contacts = ds.run();
var results = contacts.map(function(contact) {
var calcRecord = app.MyCalcModel.newRecord();
calcRecord.Name = contact.FullName;
return calcRecord;
});
return results;
Note, that you cannot return objects of arbitrary type from Server Script Query, only of type of this particular Calculated Model.
But from some parts of your description and error text if feels like you are trying to load records with async serever call using google.scritp.run. In this case you cannot return App Maker records(App Script doesn't allow this) and you need to map them to simple JSON objects.
I don't think I was super-clear on my original post.
I have a calculated model that is all of the user's contacts from Google Contacts (full name, email, mobile, etc...) On the UI I have a list widget that's populated with all of the Full Name fields and above the list widget a text input that's used to search the list widget. So the search text box's on input change event sends a request to query the Full Names, similar to how Google Contact's search feature works.
Screen Shot
It appears that App Maker doesn't let you query calculated models, so I have this workaround - unless someone comes up with something better:
This is the onInputChange handler for the search text box:
sq = app.pages.SelectClient.descendants.TextBox1.value;
app.datasources.SearchContacts.query.parameters.Name = sq;
app.datasources.SearchContacts.load();
This is the Server Script Code (thanks to #Pavel Shkleinik for the heads up):
var sq = query.parameters.Name;
if (sq !== null) {
return getContactsbyName(sq);
} else {
return getContacts();
}
And the server code with no query:
function getContacts() {
var results = [];
var contacts = ContactsApp.getContacts();
contacts.forEach(function(item) {
var contact = app.models.Contacts.newRecord();
contact.FullName = item.getFullName();
var emails = item.getEmails(ContactsApp.Field.WORK_EMAIL);
if (emails.length > 0) {
contact.PrimaryEmail = emails[0].getAddress();
}
contact.LastName = item.getFamilyName();
contact.FirstName = item.getGivenName();
var phones = item.getPhones(ContactsApp.Field.MOBILE_PHONE);
if (phones.length > 0) {
contact.Mobile = phones[0].getPhoneNumber();
}
var addresses = item.getAddresses(ContactsApp.Field.WORK_ADDRESS);
if (addresses.length > 0) {
contact.Address = addresses[0].getAddress();
}
results.push(contact);
results.sort();
});
return results;
}
And with the query:
function getContactsbyName(sq) {
var results = [];
var contacts = ContactsApp.getContactsByName(sq);
contacts.forEach(function(item) {
var contact = app.models.Contacts.newRecord();
contact.FullName = item.getFullName();
var emails = item.getEmails(ContactsApp.Field.WORK_EMAIL);
if (emails.length > 0) {
contact.PrimaryEmail = emails[0].getAddress();
}
contact.LastName = item.getFamilyName();
contact.FirstName = item.getGivenName();
var phones = item.getPhones(ContactsApp.Field.MOBILE_PHONE);
if (phones.length > 0) {
contact.Mobile = phones[0].getPhoneNumber();
}
var addresses = item.getAddresses(ContactsApp.Field.WORK_ADDRESS);
if (addresses.length > 0) {
contact.Address = addresses[0].getAddress();
}
results.push(contact);
results.sort();
});
return results;
}
This way, the list populates with all of the names when there's no search query present, and then re-populates with the search query results as needed.
The only issue is that the call to the Google Contacts App to populate the Calculated Model is sometimes very slow.
The application shows work-shifts for certain time-period. firebaseConn.getShifts is the API-function to get the shiftData for the given time period.
versions:
firebase: 2.0.6
angularFire: 0.9.0 (confirmed with 0.8.2 also)
This is my firebase schema:
And this is the code:
.factory('watchers', function(bunch-of-dependencies) {
var unbindShifts = function() {};
var inited = false;
var shifts = {};
... some irrelevant code in between ...
function initShifts() {
unbindShifts();
shifts.object = firebaseConn.getShifts( false, from, to, $scope );
$scope.shifts = shifts.object;
shifts.object.$bindTo($scope, "shifts").then(function(unbind) {
unbindShifts = unbind;
});
}
The firebase-queries (that have worked fine before adding the unbind / bind and possibly time-based querying might cause issues too):
firebaseConn.getShifts = function(asArray, from, to, scope) {
return cacheRequest(FBURL + "shifts", asArray, [from, to]);
};
function cacheRequest(url, asArray, limits) {
var type = asArray ? "array" : "object";
var startAt = limits ? limits[0] : undefined;
var endAt = limits ? limits[1] : undefined;
var retObj, FBRef;
cached[url] = cached[url] || {};
/* If there are limits-parameters we don't cache at all atm. Since those queries should be checked differently than static urls */
if(!limits && cached[url][type]) {
FBRef = cached[url][type];
} else {
FBRef = cached[url][type] = createFBRef(url, startAt, endAt);
}
if(asArray) {
retObj = FBRef.$asArray();
} else {
retObj = FBRef.$asObject();
}
return retObj;
}
function createFBRef(resourceURL, startAt, endAt) {
var modifiedObject = $firebase( createRef( resourceURL ).orderByKey().startAt(startAt).endAt(endAt) );
return modifiedObject;
}
function createRef(resourceURL) {
return new Firebase( resourceURL );
}
Now I have located the problem to be with the query limiting. If the from and to Dates are undefined, this works without problems. But I need to be able to limit the amount of data, since loading many years of workshift-data, to show a weeks time, won't be good :).
The actual problem is not displaying and fetching the data, everything works fine, it's related to the times and re-binding.
If I do any changes to e.g. "20150115"-table. For example I add another "groups"-child there. When i unbind and rebind, the whole "20150115"-table gets deleted and this holds true only to the latest changes. If I add multiple child to different dates e.g. "20150113", "20150114", "20150115" and the latest change is in "20150115" and then I unbind + re-bind another time from firebase, all the other root-paths will stay as they are, but the latest change in "20150115" will make the whole tree deleted.
I hope I make myself clear, so for safety I try to explain it again in simpler way.
- Changes to 1. "20150113", 2. "20150114", 3. "20150115" through the app.
- Changing timeline from UI causes: unbind + re-bind
- As a side-effect the whole "20150114" tree gets deleted.
The problem is somehow related to advanced querying with orderByKey().startAt(startAt).endAt(endAt) and binding.
Also for additional info. The data which is added through the UI gets added to the firebase database, but when the re-binding happens, the data is deleted from the database. Specifically on rebind, unbinding causes no issues, if I delay rebinding with timeout.
EDIT:
I have found the source of the actual issue. After the new binding is in place and everything seems to be in order, there is an angular watch event that kicks in. The event tries to save the last change user made before re-binding.
So if I have and active timeline for december (20141201 - 20141230) and I change "20141225"-data. Then change the timeline to 20150101 - 20150130, causing unbind and rebind (or manually fetching new data). There will be an event, after the binding has been done and everything seems to be in order, trying to save 20141225 data to either the new timeline (20150101 - 20150130) or the old one, not sure which one. This causes the firebase to actually delete the whole 20141225-tree, instead of saving the data.
The new data makes it into your Firebase fine, which you can see by either checking your Firebase dashboard or by running a quick snippet like this in your browser's dev console:
new Firebase("https://firebaseurl").once('value', function(s) { console.log(s.val()); })
The data even makes it back into your application. The only problem is that Angular doesn't know that new data has arrived, so it doesn't update the view with the new data.
Normally AngularFire's $asObject and $asArray methods take care of notifying AngularJS when new data arrives from Firebase. But since you are constantly creating new queries, you'll have to take care of that yourself.
There are a few ways to signal the new data to AngularJS and I'm definitely not an expert on which one is best. But if you add $scope.$apply(); to your setDays function it works:
function setDays(ref) {
var FBRange = setFBRange(ref, from, to);
var days;
unbindDays();
days = $firebase(FBRange).$asObject();
$scope.days = days;
days.$bindTo($scope, "days").then(function(unbind) {
unbindDays = unbind;
// As a result of the new binding entry gets mysteriously deleted from firebase
});
$scope.$apply(); // Tell AngularJS about the new data, so that it updates the view
function setFBRange(ref, from, to) {
return ref.orderByKey().startAt(""+from).endAt(from + to + "");
}
}
Updated Plunkr with this change (and some others to help in debugging): http://plnkr.co/edit/YZtkzUNtjQUCcw4xb2mj?p=preview
I can't make my multiple-check-box filtering system to work. I'll explain the problem, the research I've done here on stackoverflow, and why I still need help after that.
My problem is that my check boxes can't bring back the markers when I gradually unselect them. These said filters work well when I click them, because they incrementally fade away the markers associated with them. However, after just unselecting a couple of these checkboxes, all the markers are back on screen, and the last boxes don't do anything when they are finally unclicked.
This is the temporary URL of the project: http://www.lcc.gatech.edu/~amartell6/php/main12.php
This is the code where I'm getting stuck:
//this getJson function exists within an init funciton where a map
//has already been called
$.getJSON(theUrl,function(result){
$.each(result, function(i, item){
//get Longitude
var latCoord = item.coordinate;
var parenthCoord = latCoord.indexOf(",");
var partiaLat = latCoord.substr(1,parenthCoord-1);
var lat = parseFloat(partiaLat);
//alert(lat);
//get Latitude
var lngCoord = item.coordinate;
var commaCoord = lngCoord.indexOf(",");
var partiaLng = lngCoord.substr(commaCoord+1);
var lng = parseFloat(partiaLng);
//alert(lng);
// display ALL the story markers
var storyMarker;
storyMarker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),// ----- > whithin the mutidimentional array,
map: map
});
//display the stories by clicking on the markers
google.maps.event.addListener(storyMarker, 'click', function() {
var from = "From ";
if(item.end_date != ""){
item.end_date = " to " + item.end_date;
}
else{
from = "";
}
$('#output').html(
'<p><span class="selected">Type of Entry: </span>' +
item.entry_type + ' <br/><br/>'+
'<span class="selected">Title: </span>'+ item.entry_title + '<br/><br/>' +
'<span class="selected">Date(s):</span><br/>'+ from +item.start_date+
//' to '+item.end_date+'<br/><br/>'+
item.end_date+'<br/><br/>'+
'<span class="selected">Content:</span><br/><br/> '+ item.entry
+'</p>'
);
});// end of story displays
//call filters from filter funciton
filter('#evacuation-filter',item.evacuation,"Yes");
filter('#evacuation-order-filter',item.evacuation_order,"Yes");
filter('#w-nearby-filter',item.w_nearby,"Yes");
filter('#hurricane-reached-filter',item.hurricane_reached,"Yes");
filter('#outdoors-filter',item.in_out_doors,"Outdoors Most of the Time");
filter('#indoors-filter',item.in_out_doors,"Indoors Most of the Time");
filter('#food-filter',item.food,"Yes");
filter('#windows-filter',item.windows,"Yes");
filter('#power-filter',item.power,"Yes");
filter('#wounded-filter',item.wounded,"Yes");
filter('#looting-filter',item.looting,"Yes");
filter('#blackouts-filter',item.blackouts,"Yes");
filter('#trees-filter',item.trees,"Yes");
filter('#powerlines-filter',item.powerlines,"Yes");
filter('#light-filter',item.light,"Yes");
filter('#sidewalks-filter',item.sidewalks,"Yes");
filter('#buildings-filter',item.buildings,"Yes");
filter('#flooding-filter',item.flooding,"Yes");
//FILTER FUNCTION
//first parameter is the checkbox id, the second is the filter criteria
//(the filter function has to be called within the $.each loop to be within scope)
var otherFilter = false;
function filter(id, criterion1, value){
var activeFilters = [];
$(id).change(function() {
//evalute if the checkbox has been "checked" or "unchecked"
var checkBoxVal = $(id).attr("checked");
//if it's been checked:
if(checkBoxVal=="checked"){
//1 - Get markers that don't talk about the filter
if(criterion1!=value && storyMarker.getVisible()==true){
//2 - fade them away, and leave only those meet the criteria
storyMarker.setVisible(false);
otherFilter = true;
activeFilters.push(criterion1);
//document.getElementById("text3").innerHTML=activeFilters+"<br/>";
//alert(activeFilters.push(criterion1) +","+criterion1.length);
}
}
//if it's been unchecked:
else if(checkBoxVal==undefined){
//1 - Get markers that don't talk about the filter
if(criterion1!=value && storyMarker.getVisible()==false){
//2 - Show them again
storyMarker.setVisible(true);
otherFilter = false;
activeFilters.pop(criterion1);
//alert(activeFilters.pop(criterion1) +","+criterion1.length);
} //end of if to cancel filter and bring markers and stories back
}
}); // end of change event
} // end of filter function
//var otherDropDown = false;
filter2("#media-filter",item.media);
filter2("#authorities-filter",item.authorities);
//---------------
function filter2(id2,criterion2){
$(id2).change(function() {
//get the value of the drowpdown menu based on its id
var dropDownVal = $(id2).attr("value");
var all="All";
//if the value isn't "All", other filters have not been applied, and marker is on screen
if(dropDownVal!=all && otherFilter==false){
//1 - check if the marker doesn't comply with filter
if(criterion2!=dropDownVal){
//2 - fade them away if not, and leave only those meet the criteria
storyMarker.setVisible(false);
//3 - If the marker does comply with it
}else if(criterion2==dropDownVal){
//4 - keep it there
storyMarker.setVisible(true);
}//end of filter applier
//else if if the value IS "All", filters have not been applied, and marker is faded
}else if(dropDownVal==all && otherFilter==false){
//select all the possible values for the cirterion
if(criterion2!=undefined){
//and show all those markers
storyMarker.setVisible(true);
}
}
});
} //end of function filter2
}); // end of $.each
}); // end of $.getJSON
I found one related blog post. This one suggests adding a category to the markers. However, when I do that, the filters keep working the same way. I think this happens because each filter is programmed to hide every single marker that meets their selecting criteria, but each marker has more than one property they can be filtered with.
Do you know if there is a way to make the script detect how many filters point towards the same marker, and only show it back if no filters are pointing at it? This is my guess on how to solve it, even though I don't know how to make it happen in code.
Finally, if you know of alternate ways to make the filters work, let me know.
I created an application with similar logic several years ago http://www.ioos.gov/catalog/ But it was for GMap 2.0 but I think the logic would be the same.
My approach was to extend the Google maps Marker object (already bloated) with features I wanted to filter them on.
These would be all the properties you're storing in your 'click' listener and perhaps more: e.g. item.title, item_start_date, etc. whatever you eventually want to filter your marker by.
var all_markers = [];
storyMarker.end_date = item.end_date;
storMarker.title = item.title;
...
all_markers.push(storyMarker);
Then when you want to filter loop thru all the markers, check the marker value against the filter condition and setVisible(true) or false as need.
Erik already provided a solution to my problem. However, I think the community may benefit from reading other options, and I want to share the solution I came up with. Even if it may not be the most effective, it works.
In the code I just mentioned, I declared all the storyMarkers at once when the map initializes:
// display ALL the story markers
var storyMarker;
storyMarker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),// ----- > whithin the mutidimentional array,
map: map
});
Now, I added a new argument to the markers, but instead of creating a variable as in the example I had found in other post, this argument was an empty array:
storyMarker.pointer = [];
The previous filter function had three levels. The first level detected a change in the check box. The second one verified whether the check box had been checked or unchecked. The third level ran the filter on e-v-e-r-y marker, either to show it or hide it.
This is where my solution began. Within the most inner if statement of the filter function, I added a discretionary element within the pointer array:
storyMarker.pointer.push("element");
Right after this, I nested a new if statement to check if the array is not empty. If it indeed isn't empty, the program hides the marker that this array belongs to.
The program inverses the logic when a box is unchecked. It calls-off the filter, subtracts one element from the array associated with that marker, and then checks if there are other markers associated with it. The system now only shows up markers whose arrays are empty.
//alert(storyMarker.pointer);
function filter(id,criterion,value){
$(id).change(function() {
var checkBoxVal = $(id).attr("checked");
if(checkBoxVal=="checked"){
if(criterion!=value){
storyMarker.pointer.push("element");
//alert("array length: "+storyMarker.pointer.length);
if(storyMarker.pointer.length>0){
storyMarker.setVisible(false);
}
}
}
else if(checkBoxVal!="checked"){
if(criterion!=value){
storyMarker.pointer.pop("element");
//alert("array length: "+storyMarker.pointer.length);
if(storyMarker.pointer.length<=0){
storyMarker.setVisible(true);
}
}
}
});
}
In summary, the script is still clicking a marker more multiple times if the user clicks on more than one marker. The system can now recognize how many times is one marker pointed out, and only show the one that has no pointers at all.
I want to remove an individual marker from Google map. I am using version 3 API. I know how I can remove all the markers by maintaining a markerArray and setting map null for all.
For removing one by one, I am thinking to make a key value pair combination. So that I give a key and remove the particular marker. I need help over this.
Following is the code, that I use to dram marker:
function geoCodeAddresses(data) {
var markerInfo = {addressKey: '', marker:''};
for (var i = 0; i < data.length; i++) {
myLocation = data[i];
geocoder.geocode({"address":myLocation}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({map:map, position:results[0].geometry.location});
// checkpoint A
alert(myLocation);
/*
markerInfo.addressKey = myLocation;
markerInfo.marker = marker;*/
//mArray.push(markerInfo);
}
});
}
}
I will search for addresskey and remove the marker from mArray. But I get last value every time in geocode callback method. And one object got pushed every time. the var myLocation always give me the address of the last index of my array. If I alert it at check point A.
My approach is right?
Your problem is this line:
mArray.push(markerInfo);
That doesn't push the values of markerInfo into your array. It pushes a reference to markerInfo into your array. Now, on your next iteration of the loop, when you change the value of markerInfo, it changes the value pointed at by the references in the array too. So your array ends up having elements that all have the same value.
Try this instead:
mArray.push({addressKey:myLocation,marker:marker});
If that doesn't work, then this:
mArray.push({addressKey:data[i],marker:marker});