I'm writing a google docs apps script in making a google docs add-on. When the user clicks a button in the sidebar, an apps script function is called named executeSpellChecking. This apps script function makes a remote POST call after getting the document's text.
total time = time that takes from when user clicks the button, until the .withSuccessHandler(, that means until executeSpellChecking returns = 2000 ms
function time = time that takes for the executeSpellChecking call to complete from its start to its end = 1400 ms
t3 = time that takes for the remote POST call to be completed = 800ms
t4 = time that takes for the same remote POST call to complete in a VB.NET app = 200ms
Problems:
Why total time to complete is bigger than total function time by a staggering 600ms, what else happens there? shouldn't they be equal? How can I improve it?
Why t3 is bigger than t4 ? Shouldn't they be equal? Is there something wrong with POST requests when happening from .gs? How can I improve it ?
the code is (sidebar.html):
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
//var t1 = new Date().getTime();
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
//var t2 = new Date().getTime();
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//alert("total time to complete:" + (t2-t1) + "###" + go_TextAndTranslation.time);
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
and the called function code is (spellcheck.gs):
function executeSpellChecking(origin, dest, savePrefs) {
//var t1 = new Date().getTime();
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
//var t11 = new Date().getTime();
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
//var t22 = new Date().getTime();
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
//var t2 = new Date().getTime();
console.timeEnd("function time")
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
Thank you in advance for any help.
EDIT: I updated the code to use console.time according to the suggestion, the results are:
total time: 2048.001953125 ms
Jun 21, 2021, 3:01:40 PM Debug POST time: 809ms
Jun 21, 2021, 3:01:41 PM Debug function time: 1408ms
So the problem is not how time is measured. function time is 1400ms, while the time it takes to return is 2000ms, a difference of 600ms and the POST time is a staggering 800ms, instead of 200ms it takes in VB.net to make the exact same POST call.
Use console.time() and console.timeEnd():
https://developers.google.com/apps-script/reference/base/console
I modified the code for you. console.timeEnd() outputs the time duration in the console automatically, so I removed the alert for you that showed the time difference.
You might want the strings that I used as the parameter as some sort of constant variable, so there are no magic strings used twice. I hope this is of use to you.
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
function executeSpellChecking(origin, dest, savePrefs) {
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
console.timeEnd("function time");
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
I wish to alert all nodes text only. I want to go nested node and get text only
$(document).ready(function() {
var th1=0;
var th2=0;
var th3=0;
var th4=0;
var th5=0;
var th6=0;
var tbtn_nbr=0;
var tspan_nbr=0;
var tp_nbr=0;
var ta_nbr=0;
var tul_nbr=0;
var tli_nbr=0;
var title=document.getElementsByTagName('title')[0].innerHTML;
var total_div=document.getElementsByTagName('div').length;
var total_p=document.getElementsByTagName('p').length;
var total_a=document.getElementsByTagName('a').length;
var total_span=document.getElementsByTagName('span').length;
getdata("div", 0);
function getdata(tag_name, ti)
{
//alert(tag_name); alert(ti);
if(tag_name!='div'){ti--;}
//alert(ti);
var total_tag_lenght=document.getElementsByTagName(tag_name).length;
for(var ti; ti<=Number(total_tag_lenght); ti++){
var tag_inner=document.getElementsByTagName(tag_name)[ti].innerHTML;
alert(tag_inner);
ti_nbr=ti+1;
var words = tag_inner.split(" ");
var str=words[0];
var nd = str.search("<div");
var np = str.search("<p");
var na = str.search("<a");
var ns = str.search("<span");
var nh1 = str.search("<h1");
var nh2 = str.search("<h2");
var nh3 = str.search("<h3");
var nh4 = str.search("<h4");
var nh5 = str.search("<h5");
var nh6 = str.search("<h6");
var nbtn = str.search("<button");
var nul = str.search("<ul");
var nli = str.search("<li");
//alert(np);
if(nd>0)
{
getdata("div", ti_nbr);
}
else if(np>0)
{ //alert("hello");
tp_nbr++;
//alert(tp_nbr);
getdata("p", tp_nbr);
}
else if(na>0)
{ //alert("hello");
ta_nbr++;
getdata("a", ta_nbr);
}
else if(ns>0)
{ tspan_nbr++;
getdata("span", tspan_nbr);
}
else if(nh1>0)
{ th1_nbr++;
getdata("h1", th1_nbr);
}
else if(nh2>0)
{ th2_nbr++;
getdata("h2", th2_nbr);
}
else if(nh3>0)
{ th3_nbr++;
getdata("h3", th3_nbr);
}
else if(nh4>0)
{ th4_nbr++;
getdata("h4", th4_nbr);
}
else if(nh5>0)
{ th5_nbr++;
getdata("h5", th5_nbr);
}
else if(nh6>0)
{ th6_nbr++;
getdata("h6", th6_nbr);
}
else if(nbtn>0)
{ tbtn_nbr++;
getdata("button", tbtn_nbr);
}
else if(nul>0)
{ tul_nbr++;
getdata("ul", tul_nbr);
}
else if(nli>0)
{ tli_nbr++;
getdata("li", tli_nbr);
}
else
{
//alert(tag_inner);
}
}
}
});
Since you have jquery, you can select elements using "all" selector $("*").
Then you can iterate on them using "each" function
I am using chosen.jquery to convert my select to multiple select. not able to select option from chosen multiple select after sorting.
Following is my sort method. after sorting I call trigger api.
function sortSelect(fieldObj) {
var selElem = document.getElementById('partnerCasteId');
var tmpAry = new Array(); var j = 0;
for (var i=0;i<selElem.options.length;i++) {
if(selElem.options[i].value != "")
{
tmpAry[j] = new Array();
tmpAry[j] = selElem.options[i].text;
j = j + 1;
}
}
tmpAry.sort();
var i = tmpAry.length-2, prev='';
do {
if (tmpAry[i] === prev) {
tmpAry.splice(i,1);
}
prev = tmpAry[i];
} while (i-- && i>-1);
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i], tmpAry[i]);
selElem.options[i] = op;
}
return;
}
$("#partnerCasteId").trigger('chosen:updated');
I am a beginner at working with JSON and have not used it much, how do I split the genre for a tv show into individual genres and add any new genres to the options of the drop down? I want to split the genres that have a '|' and then add them to the 2nd drop-down select as options. How do I also set "Comedy" as the default option? Thanks in advance.
$(function () {
$("#chooseByGenre").click(function () {
var text = $("#yourGenre").val();
text = text.replace(/\|, " ");
var edg = text.split("");
$("#genreSelection").html("");
for (i = 0; i < edg.length; i++) {
if (edg[i] < "a" || edg[i] > "z") {
$("#genreSelection").append("<br />");
}
else {
$("#genreSelection").append('<img src="sign' + edg[i] + '.g" />');
}
}
});
code for default option:
var JSON_Response;
$(document).ready(function () {
$.getJSON('Show.json', function (data) {
JSON_Response = data;
var mySelect = document.getElementById("selShow");
for (i = 0; i < JSON_Response.shows.length; i++) {
var myOption = document.createElement("option");
myOption.text = JSON_Response.shows[i].Title;
myOption.value = i;
try {
mySelect.add(myOption, mySelect.options[null]);
}
catch (e) {
mySelect.add(myOption, null);
}
} //end for
var mySelect2 = document.getElementById("selGenre");
for (i = 0; i < JSON_Response.shows.length; i++) {
var myOption2 = document.createElement("option");
myOption2.text = JSON_Response.shows[i].Genre;
myOption2.value = i;
try {
mySelect2.add(myOption2, mySelect2.options[null]);
}
catch (e) {
mySelect2.add(myOption, null);
}
} //end for
}); //end getJSON
probably you can try like this? (haven't tested yet):
...
try {
if ( myOption2.text == 'comedy') {
myOption2.setAttribute("selected", "selected");
}
mySelect2.add(myOption2, mySelect2.options[null]);
}
...
I have found similar threads about this but I cant seem to make their solutions work for my specific issue. I currently have a calendar that will highlight the starting date of an Event. I need to change this to highlight the Start Date through the End Date.
Note: I did not write this code. It seems like whoever wrote this left a lot of junk in here. Please don't judge.
attachTocalendar : function(json, m, y) {
var arr = new Array();
if (json == undefined || !json.month || !json.year) {
return;
}
m = json.month;
y = json.year;
if (json.events == null) {
return;
}
if (json.total == 0) {
return;
}
var edvs = {};
var kds = new Array();
var offset = en4.ynevent.getDateOffset(m, y);
var tds = $$('.ynevent-cal-day');
var selected = new Array(), numberOfEvent = new Array();
for (var i = 0; i < json.total; ++i) {
var evt = json.events[i];
var s1 = evt.starttime.toTimestamp();
var s0 = s1;
var s2 = evt.endtime.toTimestamp();
var ds = new Date(s1);
var de = new Date(s2);
var id = ds.getDateCellId();
index = selected.indexOf(id);
if (index < 0)
{
numberOfEvent[selected.length] = 1;
selected.push(id);
}
else
{
numberOfEvent[index] = numberOfEvent[index] + 1;
}
}
for (var i = 0; i < selected.length; i++) {
var td = $(selected[i]);
if (td != null) {
if (!(td.hasClass("otherMonth"))){
td.set('title', numberOfEvent[i] + ' ' + en4.core.language.translate(numberOfEvent[i] > 1 ? 'events' : 'event'));
td.addClass('selected');
}
}
}
},
Instead of trying to select them all, I recommend you iterate over them instead. So something like this:
function highlightDates(startDate, endDate) {
var curDate = startDate;
var element;
$('.selected').removeClass('selected'); // reset selection
while (curDate <= endDate) {
element = getElementForDate(curDate)
element.addClass('selected');
curDate.setDate(curDate.getDate() + 1); // add one day
}
}
function getElementForDate(someDate) {
return $('#day-' + someDate.getYear() + "-" + someDate.getMonth() + "-" + someDate.getDay());
}