I'm trying to override the rfce snippet in VS code but I can't seem to be able to get the filename autofilled when there's a named file. Where the file is not saved(unnamed) it should just be NameOfComponent but if the file is saved(has a name), the snippet should name the component the same as the file name but without the extension. Here's what I have so far:
"React Component": {
"prefix": "rfce",
"body": [
"import React, { useState, useEffect } from \"react\";",
"",
"const ${1:NameOfComponent} = () => {",
" return (",
" <>",
" ${2:<div>Hello World</div>}",
" </>",
" );",
"};",
"",
"export default ${1:NameOfComponent};"
],
"description": "React Component"
}
If you want to make your snippet into a template for new files see https://stackoverflow.com/a/73043147/836330. Snippet template functionality is being built in to vscode.
Presumably you have found $TM_FILENAME_BASE from vscode snippet variables documentation as the variable you need to get the file name of the current file without its extension.
Ideally what you would like to do is a choice element (see Choice doc and something like this:
"const ${1|NameOfComponent},$TM_FILENAME_BASE|}...", // does not work
That won't work because according to the snippet grammar choice options can only be text:
choice ::= '${' int '|' text (',' text)* '|}'
So you would have to simulate a choice as close as possible. The following snippet does that in two ways:
"React Component": {
"prefix": "rfce",
"body": [
"import React, { useState, useEffect } from \"react\";",
"",
// "const ${1:NameOfComponent}${2:$TM_FILENAME_BASE} = () => {", // option 1 works
"const ${1:${2:NameOfComponent}${3:$TM_FILENAME_BASE}} = () => {", // option 2 works
" return (",
" <>",
" ${4:<div>Hello World</div>}",
" </>",
" );",
"};",
"",
"export default $1;" // uses option 2
],
"description": "React Component"
}
Option 1 simply lists both ${1:NameOfComponent}${2:$TM_FILENAME_BASE} presents both "options" - each will be selected in turn, just delete the one you don't want when it is selected and tab to go on. This is pretty straightforward but does require you to use the whole construction ${1:NameOfComponent}${2:$TM_FILENAME_BASE} every time you want that value.
Option 2 wraps the whole thing in another tabstop:
${1:${2:NameOfComponent}${3:$TM_FILENAME_BASE}}} which is a little trickier but then the result is put into tabstop $1 and then that is all you need to refer to when you want the result (as in the last line of the snippet).
You just have to practice a little - there is an extra tab at the start to select NameOfComponent. To accept it just tab past it to select the fileName and delete that, or vice versa - delete NameOfComponent when it is selected and tab to select the fileName - if you want it just tab to go on to the next tabstop.
The result of that inital tabstop will be put into $1 which can then be used elsewhere without the need to go through the option selection stuff again.
Here is a demo using option 2:
You can use TM_FILENAME_BASE - The filename of the current document without its extensions
Example for a react functional typed component:
"create react functional component": {
"prefix": "trafce",
"body": [
"import { FC } from \"react\"",
"\n",
"interface Props {\n\n}",
"\n",
"const $TM_FILENAME_BASE:FC<Props> = ({}) => {",
" return (",
" <div> ${1:$TM_FILENAME_BASE} </div>",
" )",
"}",
"\n",
"export default $TM_FILENAME_BASE"
],
"description": "Create a react-typed functional component "
}
See the demo
Demo for the code snippet
I have an HTML form which contains email addresses from various suppliers. I am creating a kind of mail merge function so I can send all the contacts a personalised email when the form is submitted. Here is my .gs file:
function sendEmail(form) {
const sSheet = SpreadsheetApp.getActiveSpreadsheet();
const file = DriveApp.getFileById(sSheet.getId());
const documentUrl = file.getUrl();
/* var toEmail = form.toAddress;
var ccEmail = form.ccAddress;
var fromEmail = "****#*****.com";
var subject = form.subject;
var message = form.message; */
var toEmail = "";
var fromEmail = "****#*****.com";
var message = "";
var hotelAddresses = [
form.toAddress1,
form.toAddress2,
form.toAddress3,
form.toAddress4,
form.toAddress5,
form.toAddress6,
form.toAddress7,
form.toAddress8,
form.toAddress9,
form.toAddress10,
form.toAddress11,
form.toAddress12,
form.toAddress13,
form.toAddress14,
form.toAddress15,
form.toAddress16,
form.toAddress17,
form.toAddress18,
form.toAddress19,
form.toAddress20,
form.toAddress21,
form.toAddress22,
form.toAddress23,
form.toAddress24,
form.toAddress25,
form.toAddress26,
form.toAddress27,
form.toAddress28,
form.toAddress29,
form.toAddress30,
form.toAddress31,
form.toAddress32,
form.toAddress33,
];
var contactNames = [
form.contactName1,
form.contactName2,
form.contactName3,
form.contactName4,
form.contactName5,
form.contactName6,
form.contactName7,
form.contactName8,
form.contactName9,
form.contactName10,
form.contactName11,
form.contactName12,
form.contactName13,
form.contactName14,
form.contactName15,
form.contactName16,
form.contactName17,
form.contactName18,
form.contactName19,
form.contactName20,
form.contactName21,
form.contactName22,
form.contactName23,
form.contactName24,
form.contactName25,
form.contactName26,
form.contactName27,
form.contactName28,
form.contactName29,
form.contactName30,
form.contactName31,
form.contactName32,
form.contactName33,
];
var days = [
form.day1,
form.day2,
form.day3,
form.day4,
form.day5,
form.day6,
form.day7,
form.day8,
form.day9,
form.day10,
form.day11,
form.day12,
form.day13,
form.day14,
form.day15,
form.day16,
form.day17,
form.day18,
form.day19,
form.day20,
form.day21,
form.day22,
form.day23,
form.day24,
form.day25,
form.day26,
form.day27,
form.day28,
form.day29,
form.day30,
form.day31,
form.day32,
form.day33,
];
var dates = [
form.date1,
form.date2,
form.date3,
form.date4,
form.date5,
form.date6,
form.date7,
form.date8,
form.date9,
form.date10,
form.date11,
form.date12,
form.date13,
form.date14,
form.date15,
form.date16,
form.date17,
form.date18,
form.date19,
form.date20,
form.date21,
form.date22,
form.date23,
form.date24,
form.date25,
form.date26,
form.date27,
form.date28,
form.date29,
form.date30,
form.date31,
form.date32,
form.date33,
];
var times = [
form.time1,
form.time2,
form.time3,
form.time4,
form.time5,
form.time6,
form.time7,
form.time8,
form.time9,
form.time10,
form.time11,
form.time12,
form.time13,
form.time14,
form.time15,
form.time16,
form.time17,
form.time18,
form.time19,
form.time20,
form.time21,
form.time22,
form.time23,
form.time24,
form.time25,
form.time26,
form.time27,
form.time28,
form.time29,
form.time30,
form.time31,
form.time32,
form.time33,
];
var additionalInfo = [
form.additional1,
form.additional2,
form.additional3,
form.additional4,
form.additional5,
form.additional6,
form.additional7,
form.additional8,
form.additional9,
form.additional10,
form.additional11,
form.additional12,
form.additional3,
form.additional14,
form.additional15,
form.additional16,
form.additional17,
form.additional18,
form.additional19,
form.additional20,
form.additional21,
form.additional22,
form.additional23,
form.additional24,
form.additional25,
form.additional26,
form.additional27,
form.additional28,
form.additional29,
form.additional30,
form.additional31,
form.additional32,
form.additional33,
];
for(var i = 0; i<times.length; i++){
var subject = "Meeting - " + days[i] + ", " + dates[i] + " at " + times[i];
toEmail = hotelAddresses[i];
message = "Dear " + contactNames[i] + ","
+"<br><br>"+
"Please confirm the meeting on " + days[i] + " " + dates[i] + " at " + times[i] + "." + "<br>" + "<br>" +
additionalInfo[i] +
" If you could kindly let me know if you are able to confirm that would be great." + "<br>" + "<br>" +
"Many thanks and I look forward to hearing from you soon." + "<br>" + "<br>" +
"Yours sincerely," + "<br>" + "<br>" +
form.yourName + "<br>" + "<br>"
+ "<em><b>" + form.yourPosition + "</b></em> <br><br>" +
"<span style='color:#0e216d'><b> Company name. </b>" + "<br>" +
GmailApp.sendEmail(
toEmail, // recipient
subject, // subject
'test', { // body
htmlBody: message // advanced options
}
);
}
}
It works fine except that sometimes the input fields for email will be blank, in which case I need the script to ignore that supplier and continue to run. At the moment it is obviously hitting the empty input and stopping the execution.
I presume I need a conditional statement of sorts... something along the lines of if(hotelAddresses[i] != null) {}
But I cannot work out where to insert this...
Additional: 31 Aug 18
For the HTML I have a series of objects (33 in total) that are all set up like this:
<input type="checkbox" id="check1" class="check" checked>
<input type="text" id="name1" class="contactNameInput" name="toAddress1">
<input type="text" id="contactName1" class="contactNameInput mailName" name="contactName1">
<input type="text" id="time1" class="contactNameInput hidden mailTime" name="time1">
<input type="text" id="day1" class="contactNameInput hidden mailDay" name="day1">
<input type="text" id="date1" class="contactNameInput hidden mailDate" name="date1">
<textarea class="additional contactNameInput" id="additional1" name="additional1" placeholder="Additional requests..."></textarea>
<div class="preview1"></div>
You want to separate the cases with and without hotelAddresses[i] using a script like if(hotelAddresses[i] != null) {}. When my understanding is correct, how about this modification?
Modification points:
Do you want to add after "<span style='color:#0e216d'><b> Company name. </b>" + "<br>" +? In the current script, it's "<span style='color:#0e216d'><b> Company name. </b>" + "<br>" + GmailApp.sendEmail(...). If you want to add more strings, please put them. If you don't want to add, please remove the last +.
I think that the script of if(hotelAddresses[i] != null) {} can be used in the for loop.
The script which reflected above is as follows.
Modified script:
In this modified script, the script of for loop was modified.
for(var i = 0; i<times.length; i++) {
var toEmail = hotelAddresses[i];
if (toEmail) {
var subject = "subject";
var message = "messages";
GmailApp.sendEmail(toEmail, subject, 'test', {htmlBody: message});
} else {
// do something
}
}
Note:
In this modified script, subject and message are replaced by "subject" and "messages", respectively. So please modify them for your situation.
If you want to do something when hotelAddresses[i] is null, please modify // do something.
If you don't want to do something when hotelAddresses[i] is null, please remove else {}.
If I misunderstand your question, please tell me. I would like to modify it.
I am facing an issue where all of my text e-mails are scrunched together and do not have new lines persisting through the sending process.
Here is the code:
def send_ses_message(email_to, subject, body):
ses = init_ses_internal()
if ses:
ses.send_email(
Source='no-reply#domain.com',
Destination={
'ToAddresses': [
email_to,
],
},
Message={
'Subject': {
'Data': subject,
},
'Body': {
'Text': {
'Data': body,
'Charset': 'UTF-8',
},
'Html': {
'Data': body,
'Charset': 'UTF-8',
},
}
},
ReplyToAddresses=[
'mharris#domain.com', # just in case someone replies to a no-reply# address I'll receive them
],
ReturnPath='mharris#domain.com', # bounce backs will come to me also
)
return True
I have most recently tried forcing UTF-8 hoping that would allow the newlines to persist. After that I added \n where a new line should exist.
Here is an example of a email:
def send_reset_email(self, email_to, unique_id):
subject = "Company Password Reset"
body = """
Hello!\n\n
We have received a request to reset your password.\n
Please click the link below to proceed with resetting your password. Note: this link will expire in 1 hour.\n\n
http://staging.domain.com/password/reset/{}\n\n
If you did not request this reset you can safely ignore this e-mail.\n\n
Thank you for choosing Company!\n\n
The Company Team\n
www.company.com\n
""".format(unique_id)
send_ses_message(email_to, subject, body)
Please let me know what I can do to ensure that newlines are persistent across Amazon SES. Thanks!
The default content type in SES seems to be text/html, so using <br> instead of \n worked for me
Edit: I was having a similar issue with outlook 2013 clients. Adding a tab character before the newline worked for me.
Replacing \n with \t\n
Or \t\r\n
How do I format a String in an email so Outlook will print the line breaks?
I faced similar issue in sending a contents of log file (stored in variable) to HTML BODY.
Replacing the new line with "<br />" as below helped solve the problem. Below command replaces all newline characters in the text with "<br />".
mytext = mytext.split("\n").join("<br />")
I am trying to implement an autocomplete list using the Ajax toolkit: AutoCompleteExtender
How to achieve the following behaviours using Ajax toolkit: AutoCompleteExtender?
Can provide any code examples also?
Like google search, when the autocomplete list if display base on the inputs. When the mouse is move out or focus on other area. The autocomplete list is still showing base on the input value.
If user enter abc and system display autocompletelist like abcd, abcde. When user move the mouse out and then click back the same input abc system should again display the autocomplete list.
Can anyone advise?
I personally prefer using jQuery UI Autocomplete.
Demo & Code:
jQuery UI Autocomplete
Sample JS Code:
$(function() {
function log( message ) {
$( "<div>" ).text( message ).prependTo( "#log" );
$( "#log" ).scrollTop( 0 );
}
$( "#city" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "http://ws.geonames.org/searchJSON",
dataType: "jsonp",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: request.term
},
success: function( data ) {
response( $.map( data.geonames, function( item ) {
return {
label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
value: item.name
}
}));
}
});
},
minLength: 2,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
},
close: function() {
$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
}
});
});
Your first point is the ajax ACE (Auto Complete Extender) default behavior.
the second one, you can use jquery .mouseleave() and .mouseenter() event to shave your contextKey in a hidden field on mouse leave and fill it again in mouse enter.