My code is based on the example of google code:
https://developers.google.com/maps/articles/phpsqlinfo_v3
and was working fine.
I need to change a former 'gid' (Integer) field to 'id' (String) to get saved to the database and used to display a new labeled symbol on the map.
The strange thing is, that the url, that is build in the code to call the addrow.php file is OK. When I capture this string with alert(url), and I manually use this string, the new data is added to the database.
In my script, the call seems to fail (responseCode == 200 && data.length <=1), since no data is written to the database and the alert from the 'else-clause' is displayed as short pop-up.
Here's the code I use in my project (to save data from a form):
//save new marker to Postgis-database and add new markerwithlabel on the fly
function saveData(){
var gender = escape(document.getElementById("gender").value);
var hoehe = InZahl(document.getElementById("hoehe").value);
var breite = InZahl(document.getElementById("breite").value);
var id = escape(document.getElementById("id").value);
var vital = document.getElementById("vital").value;
var typ = document.getElementById("typ").value;
var ein_mehr = document.getElementById("ein_mehr").value;
var st_durchm = document.getElementById("st_durchm").value;
var frucht = document.getElementById("frucht").value;
var anmerk = document.getElementById("anmerk").value;
var latlng = marker.getPosition();
var url = "./mapdata/addrow.php?gender=" + gender +
"&hoehe=" + hoehe + "&lat=" + latlng.lat() + "&lng=" + latlng.lng() +
"&breite=" + breite + "&id=" + id + "&typ=" + typ + "&ein_mehr=" +ein_mehr + "&st_durchm=" + st_durchm +
"&frucht=" + frucht +
"&vital=" + vital + "&anmerk=" + anmerk;
downloadUrl(url, function (data, responseCode) {
if (responseCode == 200 && data.length <=1) {
infowindow.close();
marker.setDraggable(false);
marker.setIcon('./images/mm_purple.png');
marker.labelContent = id;
marker.setMap(map);
downloadUrl("./mapdata/getxml_get_last.php", function (data1) {
var xml = parseXml(data1);
var ms = xml.documentElement.getElementsByTagName("m");
var gid = ms[0].getAttribute("gid");
var html_n = "<div id='InfoWindow'><p style='font-weight:bold;'>" + id + "</p> \n\<p>Höhe:" + hoehe + " Breite: "+ breite +
"<br />\n\Typ: "+typ+" Stämme: "+ein_mehr+" St-Durchm: "+ st_durchm + "<br />\n\Vitalität: "+vital+" Fruchtbehang: "+frucht+
"<p/>\n\<p style='text-align:right;'><a href='sm_juniperus.php?operation=ssearch&ResetFilter=0&SearchField=gid&FilterType=%3D&FilterText="+ gid +
"' target='_blank'> Daten editieren </a></p></div>";
infowindow.setContent(html_n);
bindInfoWindow(marker, map, infowindow, html_n);
(function(i, marker, gid) {
var origIcon = marker.getIcon();
new LongPress(marker, 1000);
google.maps.event.addListener(marker, 'longpress', function(e) {
marker.setDraggable(true);
marker.setIcon(mmcross);
});
google.maps.event.addListener(marker, 'dragend', function(){
updatePosition(marker, gid);
marker.setIcon(origIcon);
});
})(i,marker,gid);
//add new marker to markerCluster-Array and to markerArray
markerCluster.addMarker(marker,false);
markerArray.push(marker);
i++;
}); // End add new marker
}
else {
alert("Your data couldn't be saved!");
}
}); // End downloadUrl
}; // END saveData()
As I said, my code worked fine, but after 3 evenings passed to solve this, I thought it would be time to ask for help.
If anybody has an idea, where the mistake lies, I would apreciate any hint.
Just to confirm, you're aware that you by doing
if (responseCode == 200 && data.length <=1) {
you are saying 'if the request is successful and the data it returns is only one character or below in length'? I am unsure if this is intended or not, because this way the code inside the if statement is only ran if the response is successful but contains only 1 or 0 characters.
Related
Background: I am a teacher. I gave a test through Forms. I graded the test by using various background colors on each cell (which represented an answer to a question by a student). Each row of the sheet has their email address in Column B.
Problem: I would like to email the entire row, including formatting, to that address in Column B so that each student has a record of their answers and how I graded them.
Question: How can I email a row of data, including formatting?
I am working with the following script, which works well for emailing a single cell without formatting:
`function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = row[0]; // I want the whole row, including formatting.
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
ContentService.createTextOutput("hello world!");
}
}`
Here it is.
I decided to add another function as it makes it a little cleaner. You'll be able to adjust the styles of the output by playing with the css styles. If you keep the commented lines your can use them for debugging. I tested the code with them and it looks good. So let me know how it works on the emails.
function sendEmails()
{
var br='<br />';
var sheet=SpreadsheetApp.getActiveSheet();
var dataRange=sheet.getDataRange();
var dataA=dataRange.getValues();
var backA=dataRange.getBackgrounds();
//var s='';//Please leave the commented lines. If needed for the future they are handy to have
for (var i=1;i<dataA.length;i++)
{
var emailAddress=dataA[i][1];
var message=formatRow(sheet.getName(),dataA[i],backA[i],dataA[0]);
var subject="Sending emails from a Spreadsheet";
//s+=br + '<strong>EmailAddress:</strong>' + emailAddress + br + '<strong>Subject:</strong>' + subject + br + message + '**************************************' + br;
MailApp.sendEmail({to:emailAddress,subject:subject,htmlBody:message});
}
//var userInterface=HtmlService.createHtmlOutput(s);
//SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Email Message')
}
I just noticed the yellow background so I quickly added another section for it.
//assume Timestamp,EmailAddres,Score,FirstName,LastName,Section...
function formatRow(sheetName,rowA,rowbackA,titleA)
{
var br='<br />';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(sheetName);
var html='';
if(rowA && rowbackA)
{
html='';
for(var j=0;j<rowA.length;j++)
{
switch(rowbackA[j])
{
case '#ff0000':
html+=br + '<span style="font-weight:600;font-size:20px;">' + titleA[j] + ':</span>' + br + '<span style="background-color:#ff0000;">' + rowA[j] + '</span>' + br;
break;
case '#ffff00':
html+=br + '<span style="font-weight:600;font-size:20px;">' + titleA[j] + ':</span>' + br + '<span style="background-color:#ffff00;">' + rowA[j] + '</span>' + br;
break;
case '#ffffff':
html+=br + '<span style="font-weight:600;font-size:20px;">' + titleA[j] + ':</span>' + br + '<span style="background-color:#ffffff;">' + rowA[j] + '</span>' + br;
break
}
}
}
return html;
}
Just a reminder I'm using #ff0000 for red so don't change to a different shade without making a change to the code.
In the event that one student's email gets eaten by the dog, you might like to send just one email.
function sendOneEmail(firstName,lastName)
{
if(firstName && lastName)
{
var br='<br />';
var sheet=SpreadsheetApp.getActiveSheet();
var dataRange=sheet.getDataRange();
var dataA=dataRange.getValues();
var backA=dataRange.getBackgrounds();
//var s='';//Please leave the commented lines. If needed for the future they are handy to have
for (var i=1;i<dataA.length;i++)
{
if(firstName==dataA[i][3] && lastName==dataA[i][4])
{
var emailAddress=dataA[i][1];
var message=formatRow(sheet.getName(),dataA[i],backA[i],dataA[0]);
var subject="Sending emails from a Spreadsheet";
//s+=br + '<strong>EmailAddress:</strong>' + emailAddress + br + '<strong>Subject:</strong>' + subject + br + message + '**************************************' + br;
MailApp.sendEmail({to:emailAddress,subject:subject,htmlBody:message});
}
}
//var userInterface=HtmlService.createHtmlOutput(s);
//SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Email Message')
}
}
Here's a birds eye view of the Spreadsheet.
I always identify element on my screen with isDisplayed/isPresent and then add if/else to perform further test. But else part of the screen never get executed and get error like "Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By(css selector, .noga-selected-summary.list.ng-scope.layout-row)" on console log.
Test_PO.js is as follow,
var ProfilePO = function(){
this.Setting = element.all(by.css('.md-icon-button.md-button.md-dark-theme.md-ink-ripple')).get(1);
this.SettingSubMenus = element.all(by.css('.md-tab.ng-scope.ng-isolate-scope.md-ink-ripple'));
//this.ReqProductLabel = element(by.css('[ng-show="ngModel && ngModel.length > 0"]'));
this.BusinessPage = element(by.css('[ng-model="required_categories"]'));
this.AddProductButton = element(by.css('[ng-click="addCategory()"]'));
this.AddedProdCat = element.all(by.css('.noga-selected-summary.list.ng-scope.layout-row'));
this.DeleteAddedProd = element.all(by.css('[ng-click="removeCategory(category)"]'));};
module.exports = ProfilePO;
test_spec.js is as follow,
it('Verify user can add required products on business screen using Find Product or Service Dropdown', function() {
Profile.AddedProdCat.get(0).isDisplayed().then(function(AddedProdCatIsDisplayed){
console.log('Added Prod Cat Is Displayed: ' + AddedProdCatIsDisplayed);
if (AddedProdCatIsDisplayed) {
Profile.AddedProdCat.count().then(function(count){
var Count1 = count;
var C1 = Count1-1;
console.log('Product list has ' + count + ' products');
for (var i=0, j=0; i <= C1 ; i++) {
Profile.DeleteAddedProd.get(j).click();
console.log('deleted ' + (i+1) + ' product');
browser.sleep(2000);
}
});
} else {
FuncLib.NogaList.isDisplayed().then(function(NogaListIsDisplayed) {
console.log('Find Product or Service Dropdown Is Displayed: ' + NogaListIsDisplayed);
if (NogaListIsDisplayed) {
FuncLib.SltNogaCat("A011100"); //select Noga
Profile.AddProductButton.isDisplayed().then(function (AddProdButtonDisplayed){
console.log('Add product button is displayed: ' + AddProdButtonDisplayed);
Profile.AddProductButton.click();
browser.sleep(3000);
Profile.AddedProdCat.isDisplayed().then(function(AddedProdCatIsDisplayed){
console.log('Added Prod Cat Is Displayed: ' + AddedProdCatIsDisplayed);
expect(Profile.AddedProdCat.getText()).toEqual('A011100');
});
});
} else
console.log('Noga Catagory dropdown is not displayed');
});
}
});
});
When"added product category list" is available on screen, this script works nicely but if I don't have added product category list, it returns above mentioned error. I tried using isPresent instead of isDisplayed but still I get same error. Kindly tell me what I need to do to handle this error?
What version of protractor you are using? This should be fixed starting from 3.3.0 - https://github.com/angular/protractor/commit/bd78dfc79b1435d124c994482df6879066079a4d
I think your this.AddedProdCat takes some time to get displayed.
You can use just wait using Expected Conditions for that element, something like this -
it('Verify user can add required products on business screen using Find Product or Service Dropdown', function() {
var EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(Profile.AddedProdCat.get(0)), 5000);
Profile.AddedProdCat.get(0).then(function(firstElement){
console.log('Added Prod Cat firstElement: ' + firstElement);
if (firstElement) {
Profile.AddedProdCat.count().then(function(count){
var Count1 = count;
var C1 = Count1-1;
console.log('Product list has ' + count + ' products');
for (var i=0, j=0; i <= C1 ; i++) {
Profile.DeleteAddedProd.get(j).click();
console.log('deleted ' + (i+1) + ' product');
browser.sleep(2000);
}
});
}
});
I would like to create a query that will allow a user to type in a starting date, and print out all records of a table from that date until the current time. I keep getting "Error 102: invalid field type for find". Any suggestions?
function billingReport(){
startDate = new Date(document.getElementById("startDate").value);
var caseList = Parse.Object.extend("Cases");
var query = new Parse.Query(caseList);
query.greaterThanOrEqualTo("createdAt", "startDate");
query.find({
success: function(results) {
alert("Successfully retrieved " + results.length + " scores.");
// Do something with the returned Parse.Object values
for (var i = 0; i < results.length; i++) {
var object = results[i];
alert(object.id + ' - ' + object.get('playerName'));
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
mentioned in a comment above, but I just wanted to end this topic correctly. The two date objects were of different types, so i added .toISOString to the startDate object and it worked like a charm
I'm trying to create a script for a student attendance spreadsheet that will look in Column E for the string "X". For each instance of "X", the string from column A (the student name) will be added to the body of an email. I'm pretty new to JavaScript, although I have been studying the basics. I've done a lot of research and found some scripts I was able to modify to send an individual email for each instance of X in E. However, I have not been able to figure out how to combine that information into a single email.
Here's what I have so far:
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
EMAIL_SENT = "EMAIL_SENT",
statusArray = sheet.getDataRange().getValues();
var class = statusArray[0][8],
status = "X",
email = "XXXX"
for (i=7;i < statusArray.length;i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
var body = "This is a No-Show Report for " +student+ " from " + class;
var subject = "No-Show Report for " + student+ " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
sheet.getRange(i+1, 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
I realize I'll probably need to move the sendEmail function to be outside the IF statement. I tried to create an array with the names and join those into a string and add it to the body of the email, but I've had no luck. It just ended up sending the last name instead of all of them.
If anyone has any suggestions for me I would be deeply grateful.
First set up variables to keep track of which student did not show up:
var students = [];
var student_rows = [];
Then, add student to these arrays when X is found:
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
students.push(student);
student_rows.push(i+1);
}
Then send the email with all student names combined (outside of the for loop like you said)
var body = "This is a No-Show Report for " + students.join(', ') + " from " + class;
var subject = "No-Show Report for " + students.join(', ') + " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
Finally update the spreadsheet indicating which names were in that email:
for (var i=0; i<student_rows.length; i++) {
sheet.getRange(student_rows[i], 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
Here's the complete script:
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
EMAIL_SENT = "EMAIL_SENT",
statusArray = sheet.getDataRange().getValues();
var class = statusArray[0][8],
status = "X",
email = "francis#bposolutions.com";
var students = [];
var student_rows = [];
for (i=7;i < statusArray.length;i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
students.push(student);
student_rows.push(i+1);
}
}
var body = "This is a No-Show Report for " + students.join(', ') + " from " + class;
var subject = "No-Show Report for " + students.join(', ') + " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
for (var i=0; i<student_rows.length; i++) {
sheet.getRange(student_rows[i], 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
There are probably many ways to implement a new version of your code, the other answer probably works but I think it can be improved (a bit).
First of all, you can get rid of the flush method that does nothing else than slowing down the function (it was originally used in the Google example to check the sent status row by row, it is useless when we send only one mail with all the data in it)
Secondly, it might be a good idea to use html format to get a better looking result.
And lastly, it is good practice to write back to the sheet using one setValues instead of multiple setValue() in a loop.
Here is a possible replacement code, you'll have to "tune" it to your needs to eventually improve the message format but the main structure is there and working.
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
statusArray = sheet.getDataRange().getValues();
var email = Session.getActiveUser().getEmail(); //replace with the email you want, this value will send mails to you I used it for test.
var class = statusArray[0][8],
status = "X",
students = [];
for (var i=7;i < statusArray.length; i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != "EMAIL_SENT") {
students.push(statusArray[i][0]);
statusArray[i][84]="EMAIL_SENT";
}
}
var subject = "No-Show Report for " + students.length + " from " + class;
var textBody = "This is a No-Show Report for " +students.length+ " from " + class+"\n";
var HTMLBody = "<b>This is a No-Show Report for " +students.length+ " from " + class+"</b><br><br>"
+'<table style="background-color:lightblue;border-collapse:collapse;" border = 1 cellpadding = 5><th>Sent Mails</th><tr>';
for(var n in students){
HTMLBody += '<tr><td>'+n+'</td><td>'+statusArray[n][0]+'</td></tr>';
textBody += '\n'+n+' - '+statusArray[n][0];
}
HTMLBody+='</table><BR> kind regards.' ;
textBody+='\n\nKind regards';
Logger.log(HTMLBody);
Logger.log(textBody);
MailApp.sendEmail(email,subject,textBody,{'NoReply' : true, 'htmlBody' : HTMLBody});
sheet.getRange(1,1,statusArray.length,statusArray[0].length).setValues(statusArray);
}
The question I have is how I would be able to change the value that is set in the text box that the autocomplete is linked to. The task I am attempting to do is to convert from YUI 2 to YUI 3. Please don't say that I shouldn't do that... because It isn't my choice. I am aware... The code below is what was used before. I already have the autocomplete functionality doing most of what it needs to do. It's just when it gets to the field.itemSelectEvent.subscribe(myHandler) part that I can no longer get anything else to work. The list comes up with the persons information but when selected it just puts [object Object] in the text box instead of their name that automatically forwards to another page. Thank you for your help!!!
var field = new YAHOO.widget.AutoComplete("webUserSearch",
"webUserSearchContainer", oDS);
field.highlightClassName = "autoCompleteHighlight";
field.useShadow = true;
field.queryMatchContains = true;
field.maxResultsDisplayed = 20;
field.resultTypeList = false;
field.formatResult = function(oResultData, sQuery) {
return "<div class=\"result\"><u style=\"cursor:pointer\">"
+ oResultData['Last Name'] + ", " + oResultData['First Name']
+ "</u> (" + oResultData['User Name'] + ")</div>";
};
var myHandler = function(sType, aArgs) {
var theField = aArgs[0];
var selectedElement = aArgs[1];
var repObject = aArgs[2];
theField.getInputEl().value = repObject['Last Name'] + ", "
+ repObject['First Name'];
var newTabURL = <URL Removed for Stack Overflow>;
window.location.href = newTabURL;
};
field.itemSelectEvent.subscribe(myHandler);
Listen for the select event, then in the handler for that you'll get a result object. The structure of that is described in the docs for the result event (a little up from the select event).
I usually take a value out of the raw property on the result object to stick into the field.
resultTextLocator was the ticket. All I had to do was to return the value I wanted to display in the box.
resultTextLocator : function (result) {
return result["Last Name"] +
', ' +
result["First Name"];
}